diff --git a/src/contacts.ts b/src/contacts.ts index 9ff8ade..517040e 100644 --- a/src/contacts.ts +++ b/src/contacts.ts @@ -13,22 +13,28 @@ const contactHistoryMap: { [pubkey: string]: Event[]; } = {}; +const hasOwnContactList = () => { + return !!contactHistoryMap[config.pubkey]; +}; + /** * returns true if user is following pubkey */ -export const isFollowing = (id: string) => { +export const isFollowing = (pubkey: string) => { const following = contactHistoryMap[config.pubkey]?.at(0); if (!following) { return false; } - return following.tags.some(([tag, value]) => tag === 'p' && value === id); + return following.tags.some(([tag, value]) => tag === 'p' && value === pubkey); }; export const updateFollowBtn = (pubkey: string) => { - const followBtn = getViewElem('followBtn'); - if (followBtn) { + const followBtn = getViewElem(`followBtn-${pubkey}`); + const view = getViewOptions(); + if (followBtn && (view.type === 'contacts' || view.type === 'profile')) { const hasContact = isFollowing(pubkey); - followBtn.textContent = hasContact ? 'unfollow' : 'follow'; + const isMe = config.pubkey === pubkey; + followBtn.textContent = isMe ? 'following' : hasContact ? 'unfollow' : 'follow'; followBtn.classList.remove('primary', 'secondary'); followBtn.classList.add(hasContact ? 'secondary' : 'primary'); followBtn.hidden = false; @@ -40,25 +46,49 @@ const updateFollowing = (evt: Event) => { if (evt.pubkey === config.pubkey) { localStorage.setItem('follwing', JSON.stringify(evt)); } - if (view.type === 'profile') { - updateFollowBtn(view.id); - if (view.id === evt.pubkey) { - // update following link - const following = getViewElem('following') as HTMLElement; - if (following) { - const count = evt.tags.filter(isPTag).length; - const anchor = elem('a', { - data: {following: evt.pubkey}, - href: `/${evt.id}`, - title: dateTime.format(evt.created_at * 1000), - }, [ - 'following ', - elem('span', {className: 'highlight'}, count), - ]); - following.replaceWith(anchor); - setViewElem('following', anchor); + switch(view.type) { + case 'contacts': + if (hasOwnContactList()) { + const lastContactList = contactHistoryMap[config.pubkey]?.at(1); + if (lastContactList) { + const [added, removed] = findChanges(evt, lastContactList); + [ + ...added.map(([, pubkey]) => pubkey), + ...removed.map(([, pubkey]) => pubkey), + ].forEach(updateFollowBtn); + } else { + evt.tags + .filter(isPTag) + .forEach(([, pubkey]) => updateFollowBtn(pubkey)); + } } - } + break; + case 'profile': + updateFollowBtn(view.id); + if (view.id === evt.pubkey) { + // update following link + const following = getViewElem('following') as HTMLElement; + if (following) { + const count = evt.tags.filter(isPTag).length; + const anchor = elem('a', { + data: {following: evt.pubkey}, + href: `/contacts/${nip19.npubEncode(evt.pubkey)}`, + title: dateTime.format(evt.created_at * 1000), + }, [ + 'following ', + elem('span', {className: 'highlight'}, count), + ]); + following.replaceWith(anchor); + setViewElem('following', anchor); + } + } + break; + } +}; + +export const refreshFollowing = (id: string) => { + if (contactHistoryMap[id]?.at(0)) { + updateFollowing(contactHistoryMap[id][0]); } }; @@ -148,12 +178,29 @@ export const updateContactList = (evt: Event) => { return [evt.tags.filter(isPTag)]; }; -export const getContacts = () => { - const following = contactHistoryMap[config.pubkey]?.at(0); // TODO: ensure newest contactlist - if (following) { - return following.tags - .filter(isPTag) - .map(([, pubkey]) => pubkey); +/** + * returns list of pubkeys the given pubkey is following + * @param pubkey + * @returns {String[]} pubkeys + */ +export const getContacts = (pubkey: string) => { + const following = contactHistoryMap[pubkey]?.at(0); + if (!following) { + return []; + } + return following.tags + .filter(isPTag) + .map(([, pubkey]) => pubkey); +}; + +/** + * returns list of pubkeys the user is following, if none found it will try from localstorage + * @returns {String[]} pubkeys + */ +export const getOwnContacts = () => { + const following = getContacts(config.pubkey); + if (following.length) { + return following; } const followingFromStorage = localStorage.getItem('follwing'); if (followingFromStorage) { @@ -186,9 +233,9 @@ const updateContactTags = ( ]; }; -export const followContact = async (id: string) => { - const followBtn = getViewElem('followBtn') as HTMLButtonElement; - const statusElem = getViewElem('followStatus') as HTMLElement; +export const followContact = async (pubkey: string) => { + const followBtn = getViewElem(`followBtn-${pubkey}`) as HTMLButtonElement; + const statusElem = getViewElem(`followStatus-${pubkey}`) as HTMLElement; if (!followBtn || !statusElem) { return; } @@ -197,7 +244,7 @@ export const followContact = async (id: string) => { kind: 3, pubkey: config.pubkey, content: '', - tags: updateContactTags(id, following), + tags: updateContactTags(pubkey, following), created_at: Math.floor(Date.now() * 0.001), }; @@ -234,5 +281,4 @@ export const followContact = async (id: string) => { console.info(`event published by ${relay}`); }); } - }; diff --git a/src/index.html b/src/index.html index dd0e1c0..beaf0a6 100644 --- a/src/index.html +++ b/src/index.html @@ -6,7 +6,7 @@