this repo has no description
1import mem from './mem';
2import store from './store';
3
4export function getAccounts() {
5 return store.local.getJSON('accounts') || [];
6}
7
8export function saveAccounts(accounts) {
9 store.local.setJSON('accounts', accounts);
10}
11
12export function getAccount(id) {
13 const accounts = getAccounts();
14 const account = id ? accounts.find((a) => a.info.id === id) : accounts[0];
15 if (!account) return null;
16 account.lastAccessedAt = Date.now();
17 setTimeout(() => {
18 saveAccounts(accounts);
19 }, 1);
20 return account;
21}
22
23export function getAccountByAccessToken(accessToken) {
24 const accounts = getAccounts();
25 return accounts.find((a) => a.accessToken === accessToken);
26}
27
28export function getAccountByInstance(instance) {
29 const accounts = getAccounts();
30 return accounts.find((a) => a.instanceURL === instance);
31}
32
33export function hasAccountInInstance(instance) {
34 const accounts = getAccounts();
35 return accounts.some((a) => a.instanceURL === instance);
36}
37
38const standaloneMQ = window.matchMedia('(display-mode: standalone)');
39
40export function getCurrentAccountID() {
41 try {
42 const id = store.session.get('currentAccount');
43 if (id) return id;
44 } catch (e) {}
45 if (standaloneMQ.matches) {
46 try {
47 const id = store.local.get('currentAccount');
48 if (id) return id;
49 } catch (e) {}
50 }
51 return null;
52}
53
54// Memoized version of getCurrentAccountID for performance
55export const getCurrentAccID = mem(
56 () => {
57 return getCurrentAccountID();
58 },
59 {
60 maxAge: 60 * 1000, // 1 minute
61 },
62);
63
64export function setCurrentAccountID(id) {
65 try {
66 store.session.set('currentAccount', id);
67 } catch (e) {}
68 if (standaloneMQ.matches) {
69 try {
70 store.local.set('currentAccount', id);
71 } catch (e) {}
72 }
73}
74
75export function getCurrentAccount() {
76 if (!window.__IGNORE_GET_ACCOUNT_ERROR__) {
77 // Track down getCurrentAccount() calls before account-based states are initialized
78 console.error('getCurrentAccount() called before states are initialized');
79 if (import.meta.env.DEV) console.trace();
80 }
81 const currentAccount = getCurrentAccountID();
82 const account = getAccount(currentAccount);
83 return account;
84}
85
86export function getCurrentAccountNS() {
87 const account = getCurrentAccount();
88 const {
89 instanceURL,
90 info: { id },
91 } = account;
92 return `${id}@${instanceURL}`;
93}
94
95export function saveAccount(account) {
96 const accounts = getAccounts();
97 const acc = accounts.find((a) => a.info.id === account.info.id);
98 if (acc) {
99 acc.info = account.info;
100 acc.instanceURL = account.instanceURL;
101 acc.accessToken = account.accessToken;
102 acc.vapidKey = account.vapidKey;
103 } else {
104 accounts.push(account);
105 }
106 saveAccounts(accounts);
107}
108
109export function updateAccount(accountInfo) {
110 // Only update if displayName or avatar or avatar_static is different
111 const accounts = getAccounts();
112 const acc = accounts.find((a) => a.info.id === accountInfo.id);
113 if (acc) {
114 if (
115 acc.info.displayName !== accountInfo.displayName ||
116 acc.info.avatar !== accountInfo.avatar ||
117 acc.info.avatar_static !== accountInfo.avatar_static
118 ) {
119 acc.info = {
120 ...acc.info,
121 ...accountInfo,
122 };
123 saveAccounts(accounts);
124 }
125 }
126}
127
128let currentInstance = null;
129export function getCurrentInstance() {
130 if (currentInstance) return currentInstance;
131 try {
132 const account = getCurrentAccount();
133 const instances = store.local.getJSON('instances');
134 const instance = account.instanceURL.toLowerCase();
135 return (currentInstance = instances[instance]);
136 } catch (e) {
137 console.error(e);
138 // alert(`Failed to load instance configuration. Please try again.\n\n${e}`);
139 // Temporary fix for corrupted data
140 // store.local.del('instances');
141 // location.reload();
142 return {};
143 }
144}
145
146let currentNodeInfo = null;
147export function getCurrentNodeInfo() {
148 if (currentNodeInfo) return currentNodeInfo;
149 try {
150 const account = getCurrentAccount();
151 const nodeInfos = store.local.getJSON('nodeInfos') || {};
152 const instanceURL = account.instanceURL.toLowerCase();
153 return (currentNodeInfo = nodeInfos[instanceURL] || {});
154 } catch (e) {
155 console.error(e);
156 return {};
157 }
158}
159
160// Massage these instance configurations to match the Mastodon API
161// - Pleroma
162function getInstanceConfiguration(instance) {
163 const { configuration, maxMediaAttachments, maxTootChars, pollLimits } =
164 instance;
165
166 const statuses = configuration?.statuses || {};
167 if (maxMediaAttachments) {
168 statuses.maxMediaAttachments ??= maxMediaAttachments;
169 }
170
171 if (maxTootChars) {
172 statuses.maxCharacters ??= maxTootChars;
173 }
174
175 const polls = configuration?.polls || {};
176 if (pollLimits) {
177 polls.maxCharactersPerOption ??= pollLimits.maxOptionChars;
178 polls.maxExpiration ??= pollLimits.maxExpiration;
179 polls.maxOptions ??= pollLimits.maxOptions;
180 polls.minExpiration ??= pollLimits.minExpiration;
181 }
182
183 return {
184 ...configuration,
185 statuses,
186 polls,
187 };
188}
189
190export function getCurrentInstanceConfiguration() {
191 const instance = getCurrentInstance();
192 return getInstanceConfiguration(instance);
193}
194
195export function getAPIVersions() {
196 const instance = getCurrentInstance();
197 return instance?.apiVersions || {};
198}
199
200export function getVapidKey(instance) {
201 // Vapid key has moved from account to instance config
202 const config = instance
203 ? getInstanceConfiguration(instance)
204 : getCurrentInstanceConfiguration();
205 const vapidKey = config?.vapid?.publicKey || config?.vapid?.public_key;
206 return vapidKey || getCurrentAccount()?.vapidKey;
207}
208
209export function isMediaFirstInstance() {
210 const instance = getCurrentInstance();
211 return /pixelfed/i.test(instance?.version);
212}
213
214const CREDENTIAL_APPLICATIONS_KEY = 'credentialApplications';
215
216export function storeCredentialApplication(instanceURL, credentialApplication) {
217 const stored = store.local.getJSON(CREDENTIAL_APPLICATIONS_KEY) || {};
218 stored[instanceURL] = credentialApplication;
219 store.local.setJSON(CREDENTIAL_APPLICATIONS_KEY, stored);
220}
221
222export function getCredentialApplication(instanceURL) {
223 const stored = store.local.getJSON(CREDENTIAL_APPLICATIONS_KEY) || {};
224 return stored[instanceURL] || null;
225}