this repo has no description
at main 225 lines 6.2 kB view raw
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}