You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
257 lines
7.9 KiB
257 lines
7.9 KiB
import { StorageKey } from '@/constants' |
|
import { isSameAccount } from '@/lib/account' |
|
import { randomString } from '@/lib/random' |
|
import { TAccount, TAccountPointer, TFeedType, TRelaySet, TThemeSetting } from '@/types' |
|
import { Event } from 'nostr-tools' |
|
|
|
const DEFAULT_RELAY_SETS: TRelaySet[] = [ |
|
{ |
|
id: randomString(), |
|
name: 'Global', |
|
relayUrls: ['wss://relay.damus.io/', 'wss://nos.lol/'] |
|
}, |
|
{ |
|
id: randomString(), |
|
name: 'Algo', |
|
relayUrls: ['wss://algo.utxo.one'] |
|
} |
|
] |
|
|
|
class StorageService { |
|
static instance: StorageService |
|
|
|
private relaySets: TRelaySet[] = [] |
|
private activeRelaySetId: string | null = null |
|
private feedType: TFeedType = 'relays' |
|
private themeSetting: TThemeSetting = 'system' |
|
private accounts: TAccount[] = [] |
|
private currentAccount: TAccount | null = null |
|
private accountRelayListEventMap: Record<string, Event | undefined> = {} // pubkey -> relayListEvent |
|
private accountFollowListEventMap: Record<string, Event | undefined> = {} // pubkey -> followListEvent |
|
private accountProfileEventMap: Record<string, Event> = {} // pubkey -> profileEvent |
|
|
|
constructor() { |
|
if (!StorageService.instance) { |
|
this.init() |
|
StorageService.instance = this |
|
} |
|
return StorageService.instance |
|
} |
|
|
|
init() { |
|
this.themeSetting = |
|
(window.localStorage.getItem(StorageKey.THEME_SETTING) as TThemeSetting) ?? 'system' |
|
const accountsStr = window.localStorage.getItem(StorageKey.ACCOUNTS) |
|
this.accounts = accountsStr ? JSON.parse(accountsStr) : [] |
|
const currentAccountStr = window.localStorage.getItem(StorageKey.CURRENT_ACCOUNT) |
|
this.currentAccount = currentAccountStr ? JSON.parse(currentAccountStr) : null |
|
const feedTypeStr = window.localStorage.getItem(StorageKey.FEED_TYPE) |
|
this.feedType = feedTypeStr ? JSON.parse(feedTypeStr) : 'relays' |
|
|
|
const accountRelayListEventMapStr = window.localStorage.getItem( |
|
StorageKey.ACCOUNT_RELAY_LIST_EVENT_MAP |
|
) |
|
this.accountRelayListEventMap = accountRelayListEventMapStr |
|
? JSON.parse(accountRelayListEventMapStr) |
|
: {} |
|
const accountFollowListEventMapStr = window.localStorage.getItem( |
|
StorageKey.ACCOUNT_FOLLOW_LIST_EVENT_MAP |
|
) |
|
this.accountFollowListEventMap = accountFollowListEventMapStr |
|
? JSON.parse(accountFollowListEventMapStr) |
|
: {} |
|
const accountProfileEventMapStr = window.localStorage.getItem( |
|
StorageKey.ACCOUNT_PROFILE_EVENT_MAP |
|
) |
|
this.accountProfileEventMap = accountProfileEventMapStr |
|
? JSON.parse(accountProfileEventMapStr) |
|
: {} |
|
|
|
const relaySetsStr = window.localStorage.getItem(StorageKey.RELAY_SETS) |
|
if (!relaySetsStr) { |
|
let relaySets: TRelaySet[] = [] |
|
const legacyRelayGroupsStr = window.localStorage.getItem('relayGroups') |
|
if (legacyRelayGroupsStr) { |
|
const legacyRelayGroups = JSON.parse(legacyRelayGroupsStr) |
|
relaySets = legacyRelayGroups.map((group: any) => { |
|
return { |
|
id: randomString(), |
|
name: group.groupName, |
|
relayUrls: group.relayUrls |
|
} |
|
}) |
|
} |
|
if (!relaySets.length) { |
|
relaySets = DEFAULT_RELAY_SETS |
|
} |
|
const activeRelaySetId = relaySets[0].id |
|
window.localStorage.setItem(StorageKey.RELAY_SETS, JSON.stringify(relaySets)) |
|
window.localStorage.setItem(StorageKey.ACTIVE_RELAY_SET_ID, activeRelaySetId) |
|
this.relaySets = relaySets |
|
this.activeRelaySetId = activeRelaySetId |
|
} else { |
|
this.relaySets = JSON.parse(relaySetsStr) |
|
this.activeRelaySetId = window.localStorage.getItem(StorageKey.ACTIVE_RELAY_SET_ID) ?? null |
|
} |
|
} |
|
|
|
getRelaySets() { |
|
return this.relaySets |
|
} |
|
|
|
setRelaySets(relaySets: TRelaySet[]) { |
|
this.relaySets = relaySets |
|
window.localStorage.setItem(StorageKey.RELAY_SETS, JSON.stringify(this.relaySets)) |
|
} |
|
|
|
getActiveRelaySetId() { |
|
return this.activeRelaySetId |
|
} |
|
|
|
setActiveRelaySetId(id: string | null) { |
|
this.activeRelaySetId = id |
|
if (id) { |
|
window.localStorage.setItem( |
|
StorageKey.ACTIVE_RELAY_SET_ID, |
|
JSON.stringify(this.activeRelaySetId) |
|
) |
|
} else { |
|
window.localStorage.removeItem(StorageKey.ACTIVE_RELAY_SET_ID) |
|
} |
|
} |
|
|
|
getFeedType() { |
|
return this.feedType |
|
} |
|
|
|
setFeedType(feedType: TFeedType) { |
|
this.feedType = feedType |
|
window.localStorage.setItem(StorageKey.FEED_TYPE, JSON.stringify(this.feedType)) |
|
} |
|
|
|
getThemeSetting() { |
|
return this.themeSetting |
|
} |
|
|
|
setThemeSetting(themeSetting: TThemeSetting) { |
|
window.localStorage.setItem(StorageKey.THEME_SETTING, themeSetting) |
|
this.themeSetting = themeSetting |
|
} |
|
|
|
getAccounts() { |
|
return this.accounts |
|
} |
|
|
|
findAccount(account: TAccountPointer) { |
|
return this.accounts.find((act) => isSameAccount(act, account)) |
|
} |
|
|
|
getCurrentAccount() { |
|
return this.currentAccount |
|
} |
|
|
|
addAccount(account: TAccount) { |
|
if (this.accounts.find((act) => isSameAccount(act, account))) { |
|
return |
|
} |
|
this.accounts.push(account) |
|
window.localStorage.setItem(StorageKey.ACCOUNTS, JSON.stringify(this.accounts)) |
|
return account |
|
} |
|
|
|
removeAccount(account: TAccount) { |
|
this.accounts = this.accounts.filter((act) => !isSameAccount(act, account)) |
|
delete this.accountFollowListEventMap[account.pubkey] |
|
delete this.accountRelayListEventMap[account.pubkey] |
|
delete this.accountProfileEventMap[account.pubkey] |
|
window.localStorage.setItem(StorageKey.ACCOUNTS, JSON.stringify(this.accounts)) |
|
window.localStorage.setItem( |
|
StorageKey.ACCOUNT_FOLLOW_LIST_EVENT_MAP, |
|
JSON.stringify(this.accountFollowListEventMap) |
|
) |
|
window.localStorage.setItem( |
|
StorageKey.ACCOUNT_RELAY_LIST_EVENT_MAP, |
|
JSON.stringify(this.accountRelayListEventMap) |
|
) |
|
window.localStorage.setItem( |
|
StorageKey.ACCOUNT_PROFILE_EVENT_MAP, |
|
JSON.stringify(this.accountProfileEventMap) |
|
) |
|
} |
|
|
|
switchAccount(account: TAccount | null) { |
|
if (isSameAccount(this.currentAccount, account)) { |
|
return |
|
} |
|
const act = this.accounts.find((act) => isSameAccount(act, account)) |
|
if (!act) { |
|
return |
|
} |
|
this.currentAccount = act |
|
window.localStorage.setItem(StorageKey.CURRENT_ACCOUNT, JSON.stringify(act)) |
|
} |
|
|
|
getAccountRelayListEvent(pubkey: string) { |
|
return this.accountRelayListEventMap[pubkey] |
|
} |
|
|
|
setAccountRelayListEvent(relayListEvent: Event) { |
|
const pubkey = relayListEvent.pubkey |
|
if ( |
|
this.accountRelayListEventMap[pubkey] && |
|
this.accountRelayListEventMap[pubkey].created_at > relayListEvent.created_at |
|
) { |
|
return false |
|
} |
|
this.accountRelayListEventMap[pubkey] = relayListEvent |
|
window.localStorage.setItem( |
|
StorageKey.ACCOUNT_RELAY_LIST_EVENT_MAP, |
|
JSON.stringify(this.accountRelayListEventMap) |
|
) |
|
return true |
|
} |
|
|
|
getAccountFollowListEvent(pubkey: string) { |
|
return this.accountFollowListEventMap[pubkey] |
|
} |
|
|
|
setAccountFollowListEvent(followListEvent: Event) { |
|
const pubkey = followListEvent.pubkey |
|
if ( |
|
this.accountFollowListEventMap[pubkey] && |
|
this.accountFollowListEventMap[pubkey].created_at > followListEvent.created_at |
|
) { |
|
return false |
|
} |
|
this.accountFollowListEventMap[pubkey] = followListEvent |
|
window.localStorage.setItem( |
|
StorageKey.ACCOUNT_FOLLOW_LIST_EVENT_MAP, |
|
JSON.stringify(this.accountFollowListEventMap) |
|
) |
|
return true |
|
} |
|
|
|
getAccountProfileEvent(pubkey: string) { |
|
return this.accountProfileEventMap[pubkey] |
|
} |
|
|
|
setAccountProfileEvent(profileEvent: Event) { |
|
const pubkey = profileEvent.pubkey |
|
if ( |
|
this.accountProfileEventMap[pubkey] && |
|
this.accountProfileEventMap[pubkey].created_at > profileEvent.created_at |
|
) { |
|
return false |
|
} |
|
this.accountProfileEventMap[pubkey] = profileEvent |
|
window.localStorage.setItem( |
|
StorageKey.ACCOUNT_PROFILE_EVENT_MAP, |
|
JSON.stringify(this.accountProfileEventMap) |
|
) |
|
return true |
|
} |
|
} |
|
|
|
const instance = new StorageService() |
|
|
|
export default instance
|
|
|