feat: add/remove emoji packs
This commit is contained in:
@ -140,7 +140,14 @@ export function ChatMessage({
|
|||||||
onClick={() => setShowZapDialog(true)}
|
onClick={() => setShowZapDialog(true)}
|
||||||
>
|
>
|
||||||
<Profile
|
<Profile
|
||||||
icon={ev.pubkey === streamer && <Icon name="signal" size={16} />}
|
icon={
|
||||||
|
ev.pubkey === streamer && <Icon name="signal" size={16} />
|
||||||
|
// <img
|
||||||
|
// className="badge-icon"
|
||||||
|
// src="https://nostr.build/i/nostr.build_4b0d4f7293eb0f2bacb5b232a8d2ef3fe7648192d636e152a3c18b9fc06142d7.png"
|
||||||
|
// alt="TODO"
|
||||||
|
// />
|
||||||
|
}
|
||||||
pubkey={ev.pubkey}
|
pubkey={ev.pubkey}
|
||||||
profile={profile}
|
profile={profile}
|
||||||
/>
|
/>
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.emoji-pack-title .name {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.emoji-pack-title a {
|
.emoji-pack-title a {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
@ -30,3 +34,7 @@
|
|||||||
.emoji-pack h4 {
|
.emoji-pack h4 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.emoji-pack .btn {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
@ -1,18 +1,61 @@
|
|||||||
import "./emoji-pack.css";
|
import "./emoji-pack.css";
|
||||||
import { type NostrEvent } from "@snort/system";
|
import { type NostrEvent } from "@snort/system";
|
||||||
|
import { unixNow } from "@snort/shared";
|
||||||
|
|
||||||
|
import AsyncButton from "element/async-button";
|
||||||
|
import { useLogin } from "hooks/login";
|
||||||
|
import { toEmojiPack } from "hooks/emoji";
|
||||||
import { Mention } from "element/mention";
|
import { Mention } from "element/mention";
|
||||||
import { findTag } from "utils";
|
import { findTag } from "utils";
|
||||||
|
import { USER_EMOJIS } from "const";
|
||||||
|
import { Login, System } from "index";
|
||||||
|
|
||||||
export function EmojiPack({ ev }: { ev: NostrEvent }) {
|
export function EmojiPack({ ev }: { ev: NostrEvent }) {
|
||||||
|
const login = useLogin();
|
||||||
const name = findTag(ev, "d");
|
const name = findTag(ev, "d");
|
||||||
|
const isUsed = login.emojis.find(
|
||||||
|
(e) => e.author === ev.pubkey && e.name === name,
|
||||||
|
);
|
||||||
const emoji = ev.tags.filter((e) => e.at(0) === "emoji");
|
const emoji = ev.tags.filter((e) => e.at(0) === "emoji");
|
||||||
|
|
||||||
|
async function toggleEmojiPack() {
|
||||||
|
let newPacks = [];
|
||||||
|
if (isUsed) {
|
||||||
|
newPacks = login.emojis.filter(
|
||||||
|
(e) => e.pubkey !== ev.pubkey && e.name !== name,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
newPacks = [...login.emojis, toEmojiPack(ev)];
|
||||||
|
}
|
||||||
|
const pub = login?.publisher();
|
||||||
|
if (pub) {
|
||||||
|
const ev = await pub.generic((eb) => {
|
||||||
|
eb.kind(USER_EMOJIS).content("");
|
||||||
|
for (const e of newPacks) {
|
||||||
|
eb.tag(["a", e.address]);
|
||||||
|
}
|
||||||
|
return eb;
|
||||||
|
});
|
||||||
|
console.debug(ev);
|
||||||
|
System.BroadcastEvent(ev);
|
||||||
|
Login.setEmojis(newPacks, unixNow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="emoji-pack">
|
<div className="emoji-pack">
|
||||||
<div className="emoji-pack-title">
|
<div className="emoji-pack-title">
|
||||||
|
<div>
|
||||||
<h4>{name}</h4>
|
<h4>{name}</h4>
|
||||||
<Mention pubkey={ev.pubkey} />
|
<Mention pubkey={ev.pubkey} />
|
||||||
</div>
|
</div>
|
||||||
|
<AsyncButton
|
||||||
|
className={`btn btn-primary ${isUsed ? "delete-button" : ""}`}
|
||||||
|
onClick={toggleEmojiPack}
|
||||||
|
>
|
||||||
|
{isUsed ? "Remove" : "Add"}
|
||||||
|
</AsyncButton>
|
||||||
|
</div>
|
||||||
<div className="emoji-pack-emojis">
|
<div className="emoji-pack-emojis">
|
||||||
{emoji.map((e) => {
|
{emoji.map((e) => {
|
||||||
const [, name, image] = e;
|
const [, name, image] = e;
|
||||||
|
@ -1,50 +1,47 @@
|
|||||||
import { EventKind } from "@snort/system";
|
import { EventKind } from "@snort/system";
|
||||||
|
import { unixNow } from "@snort/shared";
|
||||||
|
|
||||||
import { useLogin } from "hooks/login";
|
import { useLogin } from "hooks/login";
|
||||||
import AsyncButton from "element/async-button";
|
import AsyncButton from "element/async-button";
|
||||||
import { System } from "index";
|
import { Login, System } from "index";
|
||||||
|
|
||||||
export function LoggedInFollowButton({
|
export function LoggedInFollowButton({ pubkey }: { pubkey: string }) {
|
||||||
pubkey,
|
|
||||||
}: {
|
|
||||||
pubkey: string;
|
|
||||||
}) {
|
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
const tags = login?.follows.tags ?? []
|
const tags = login.follows.tags;
|
||||||
const relays = login?.relays
|
|
||||||
const follows = tags.filter((t) => t.at(0) === "p");
|
const follows = tags.filter((t) => t.at(0) === "p");
|
||||||
const isFollowing = follows.find((t) => t.at(1) === pubkey);
|
const isFollowing = follows.find((t) => t.at(1) === pubkey);
|
||||||
|
|
||||||
async function unfollow() {
|
async function unfollow() {
|
||||||
const pub = login?.publisher();
|
const pub = login?.publisher();
|
||||||
if (pub) {
|
if (pub) {
|
||||||
|
const newFollows = tags.filter((t) => t.at(1) !== pubkey);
|
||||||
const ev = await pub.generic((eb) => {
|
const ev = await pub.generic((eb) => {
|
||||||
eb.kind(EventKind.ContactList).content(JSON.stringify(relays));
|
eb.kind(EventKind.ContactList).content(JSON.stringify(login.relays));
|
||||||
for (const t of tags) {
|
for (const t of newFollows) {
|
||||||
const isFollow = t.at(0) === "p" && t.at(1) === pubkey;
|
|
||||||
if (!isFollow) {
|
|
||||||
eb.tag(t);
|
eb.tag(t);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return eb;
|
return eb;
|
||||||
});
|
});
|
||||||
console.debug(ev);
|
console.debug(ev);
|
||||||
System.BroadcastEvent(ev);
|
System.BroadcastEvent(ev);
|
||||||
|
Login.setFollows(newFollows, unixNow());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function follow() {
|
async function follow() {
|
||||||
const pub = login?.publisher();
|
const pub = login?.publisher();
|
||||||
if (pub) {
|
if (pub) {
|
||||||
|
const newFollows = [...tags, ["p", pubkey]];
|
||||||
const ev = await pub.generic((eb) => {
|
const ev = await pub.generic((eb) => {
|
||||||
eb.kind(EventKind.ContactList).content(JSON.stringify(relays));
|
eb.kind(EventKind.ContactList).content(JSON.stringify(login.relays));
|
||||||
for (const tag of tags) {
|
for (const tag of newFollows) {
|
||||||
eb.tag(tag);
|
eb.tag(tag);
|
||||||
}
|
}
|
||||||
eb.tag(["p", pubkey]);
|
|
||||||
return eb;
|
return eb;
|
||||||
});
|
});
|
||||||
console.debug(ev);
|
console.debug(ev);
|
||||||
System.BroadcastEvent(ev);
|
System.BroadcastEvent(ev);
|
||||||
|
Login.setFollows(newFollows, unixNow());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.live-chat .header .popout-link {
|
.live-chat .header .popout-link {
|
||||||
color: #FFFFFF80;
|
color: #ffffff80;
|
||||||
}
|
}
|
||||||
|
|
||||||
.live-chat > .messages {
|
.live-chat > .messages {
|
||||||
@ -77,15 +77,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.live-chat .message .profile {
|
.live-chat .message .profile {
|
||||||
color: #34D2FE;
|
color: #34d2fe;
|
||||||
}
|
}
|
||||||
|
|
||||||
.live-chat .message.streamer .profile {
|
.live-chat .message.streamer .profile {
|
||||||
color: #F838D9;
|
color: #f838d9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.live-chat .message a {
|
.live-chat .message a {
|
||||||
color: #F838D9;
|
color: #f838d9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.live-chat .profile img {
|
.live-chat .profile img {
|
||||||
@ -172,13 +172,13 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
background: #0A0A0A;
|
background: #0a0a0a;
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zap-container:before {
|
.zap-container:before {
|
||||||
content: '';
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -186,20 +186,28 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
margin: -1px;
|
margin: -1px;
|
||||||
background: linear-gradient(to bottom right, #FF902B, #F83838);
|
background: linear-gradient(to bottom right, #ff902b, #f83838);
|
||||||
border-radius: inherit;
|
border-radius: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zap-container .profile {
|
.zap-container .profile {
|
||||||
color: #FF8D2B;
|
color: #ff8d2b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zap-container .zap-amount {
|
.zap-container .zap-amount {
|
||||||
color: #FF8D2B;
|
color: #ff8d2b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zap-container.big-zap:before {
|
.zap-container.big-zap:before {
|
||||||
background: linear-gradient(60deg, #2BD9FF, #8C8DED, #F838D9, #F83838, #FF902B, #DDF838);
|
background: linear-gradient(
|
||||||
|
60deg,
|
||||||
|
#2bd9ff,
|
||||||
|
#8c8ded,
|
||||||
|
#f838d9,
|
||||||
|
#f83838,
|
||||||
|
#ff902b,
|
||||||
|
#ddf838
|
||||||
|
);
|
||||||
animation: animatedgradient 3s ease alternate infinite;
|
animation: animatedgradient 3s ease alternate infinite;
|
||||||
background-size: 300% 300%;
|
background-size: 300% 300%;
|
||||||
}
|
}
|
||||||
@ -224,7 +232,7 @@
|
|||||||
|
|
||||||
.zap-pill {
|
.zap-pill {
|
||||||
border-radius: 100px;
|
border-radius: 100px;
|
||||||
background: rgba(255, 255, 255, 0.10);
|
background: rgba(255, 255, 255, 0.1);
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
@ -236,7 +244,7 @@
|
|||||||
.zap-pill-icon {
|
.zap-pill-icon {
|
||||||
width: 12px;
|
width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
color: #FF8D2B;
|
color: #ff8d2b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-zap-container {
|
.message-zap-container {
|
||||||
@ -252,7 +260,7 @@
|
|||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
transition: opacity .3s ease-out;
|
transition: opacity 0.3s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1020px) {
|
@media (min-width: 1020px) {
|
||||||
@ -271,7 +279,7 @@
|
|||||||
gap: 2px;
|
gap: 2px;
|
||||||
border-radius: 100px;
|
border-radius: 100px;
|
||||||
background: rgba(255, 255, 255, 0.05);
|
background: rgba(255, 255, 255, 0.05);
|
||||||
color: #FFFFFF66;
|
color: #ffffff66;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-zap-button:hover {
|
.message-zap-button:hover {
|
||||||
@ -299,7 +307,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
border-radius: 100px;
|
border-radius: 100px;
|
||||||
background: rgba(255, 255, 255, 0.10);
|
background: rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-reaction {
|
.message-reaction {
|
||||||
@ -311,7 +319,7 @@
|
|||||||
|
|
||||||
.zap-pill-amount {
|
.zap-pill-amount {
|
||||||
text-transform: lowercase;
|
text-transform: lowercase;
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-family: Outfit;
|
font-family: Outfit;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@ -335,10 +343,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.write-emoji-button {
|
.write-emoji-button {
|
||||||
color: #FFFFFF80;
|
color: #ffffff80;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.write-emoji-button:hover {
|
.write-emoji-button:hover {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message .profile .badge-icon {
|
||||||
|
background: transparent;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: unset;
|
||||||
|
}
|
||||||
|
@ -26,7 +26,7 @@ import { ChatMessage } from "./chat-message";
|
|||||||
import { Goal } from "./goal";
|
import { Goal } from "./goal";
|
||||||
import { NewGoalDialog } from "./new-goal";
|
import { NewGoalDialog } from "./new-goal";
|
||||||
import { WriteMessage } from "./write-message";
|
import { WriteMessage } from "./write-message";
|
||||||
import { findTag, getHost } from "utils";
|
import { findTag, getTagValues, getHost } from "utils";
|
||||||
|
|
||||||
export interface LiveChatOptions {
|
export interface LiveChatOptions {
|
||||||
canWrite?: boolean;
|
canWrite?: boolean;
|
||||||
@ -80,9 +80,7 @@ export function LiveChat({
|
|||||||
}, [feed.zaps]);
|
}, [feed.zaps]);
|
||||||
|
|
||||||
const mutedPubkeys = useMemo(() => {
|
const mutedPubkeys = useMemo(() => {
|
||||||
return new Set(
|
return new Set(getTagValues(login.muted.tags, "p"));
|
||||||
login.muted.tags.filter((t) => t.at(0) === "p").map((t) => t.at(1)),
|
|
||||||
);
|
|
||||||
}, [login.muted.tags]);
|
}, [login.muted.tags]);
|
||||||
const userEmojiPacks = login?.emojis ?? [];
|
const userEmojiPacks = login?.emojis ?? [];
|
||||||
const channelEmojiPacks = useEmoji(host);
|
const channelEmojiPacks = useEmoji(host);
|
||||||
|
@ -17,7 +17,7 @@ function cleanShortcode(shortcode?: string) {
|
|||||||
return shortcode?.replace(/\s+/g, "_").replace(/_$/, "");
|
return shortcode?.replace(/\s+/g, "_").replace(/_$/, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
function toEmojiPack(ev: NostrEvent): EmojiPack {
|
export function toEmojiPack(ev: NostrEvent): EmojiPack {
|
||||||
const d = findTag(ev, "d") || "";
|
const d = findTag(ev, "d") || "";
|
||||||
return {
|
return {
|
||||||
address: `${ev.kind}:${ev.pubkey}:${d}`,
|
address: `${ev.kind}:${ev.pubkey}:${d}`,
|
||||||
@ -78,7 +78,8 @@ export function useUserEmojiPacks(
|
|||||||
}, [relatedData]);
|
}, [relatedData]);
|
||||||
|
|
||||||
const emojis = useMemo(() => {
|
const emojis = useMemo(() => {
|
||||||
return uniqBy(emojiPacks.map(toEmojiPack), packId);
|
const packs = emojiPacks.map(toEmojiPack);
|
||||||
|
return uniqBy(packs, packId);
|
||||||
}, [emojiPacks]);
|
}, [emojiPacks]);
|
||||||
|
|
||||||
return emojis;
|
return emojis;
|
||||||
|
@ -4,15 +4,9 @@ import { EventKind, NoteCollection, RequestBuilder } from "@snort/system";
|
|||||||
import { useRequestBuilder } from "@snort/system-react";
|
import { useRequestBuilder } from "@snort/system-react";
|
||||||
|
|
||||||
import { useUserEmojiPacks } from "hooks/emoji";
|
import { useUserEmojiPacks } from "hooks/emoji";
|
||||||
import { USER_EMOJIS } from "const";
|
import { MUTED, USER_EMOJIS } from "const";
|
||||||
import { System, Login } from "index";
|
import { System, Login } from "index";
|
||||||
import {
|
import { getPublisher } from "login";
|
||||||
getPublisher,
|
|
||||||
setMuted,
|
|
||||||
setEmojis,
|
|
||||||
setFollows,
|
|
||||||
setRelays,
|
|
||||||
} from "login";
|
|
||||||
|
|
||||||
export function useLogin() {
|
export function useLogin() {
|
||||||
const session = useSyncExternalStore(
|
const session = useSyncExternalStore(
|
||||||
@ -52,12 +46,7 @@ export function useLoginEvents(pubkey?: string, leaveOpen = false) {
|
|||||||
})
|
})
|
||||||
.withFilter()
|
.withFilter()
|
||||||
.authors([pubkey])
|
.authors([pubkey])
|
||||||
.kinds([
|
.kinds([EventKind.ContactList, EventKind.Relays, MUTED, USER_EMOJIS]);
|
||||||
EventKind.ContactList,
|
|
||||||
EventKind.Relays,
|
|
||||||
10_000 as EventKind,
|
|
||||||
USER_EMOJIS,
|
|
||||||
]);
|
|
||||||
return b;
|
return b;
|
||||||
}, [pubkey, leaveOpen]);
|
}, [pubkey, leaveOpen]);
|
||||||
|
|
||||||
@ -71,30 +60,25 @@ export function useLoginEvents(pubkey?: string, leaveOpen = false) {
|
|||||||
if (!data) {
|
if (!data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!session) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (const ev of data) {
|
for (const ev of data) {
|
||||||
if (ev?.kind === USER_EMOJIS) {
|
if (ev?.kind === USER_EMOJIS) {
|
||||||
setUserEmojis(ev.tags);
|
setUserEmojis(ev.tags);
|
||||||
}
|
}
|
||||||
if (ev?.kind === 10_000) {
|
if (ev?.kind === MUTED) {
|
||||||
// todo: decrypt ev.content tags
|
// todo: decrypt ev.content tags
|
||||||
setMuted(session, ev.tags, ev.created_at);
|
Login.setMuted(ev.tags, ev.created_at);
|
||||||
}
|
}
|
||||||
if (ev?.kind === EventKind.ContactList) {
|
if (ev?.kind === EventKind.ContactList) {
|
||||||
setFollows(session, ev.tags, ev.created_at);
|
Login.setFollows(ev.tags, ev.created_at);
|
||||||
}
|
}
|
||||||
if (ev?.kind === EventKind.Relays) {
|
if (ev?.kind === EventKind.Relays) {
|
||||||
setRelays(session, ev.tags, ev.created_at);
|
Login.setRelays(ev.tags, ev.created_at);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [session, data]);
|
}, [data]);
|
||||||
|
|
||||||
const emojis = useUserEmojiPacks(pubkey, { tags: userEmojis });
|
const emojis = useUserEmojiPacks(pubkey, { tags: userEmojis });
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (session) {
|
Login.setEmojis(emojis);
|
||||||
setEmojis(session, emojis);
|
}, [emojis]);
|
||||||
}
|
|
||||||
}, [session, emojis]);
|
|
||||||
}
|
}
|
||||||
|
83
src/login.ts
83
src/login.ts
@ -68,13 +68,44 @@ export class LoginStore extends ExternalStore<LoginSession | undefined> {
|
|||||||
this.#save();
|
this.#save();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSession(s: LoginSession) {
|
takeSnapshot() {
|
||||||
this.#session = s;
|
return this.#session ? { ...this.#session } : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
setFollows(follows: Array<string>, ts: number) {
|
||||||
|
if (this.#session.follows.timestamp >= ts) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.#session.follows.tags = follows;
|
||||||
|
this.#session.follows.timestamp = ts;
|
||||||
this.#save();
|
this.#save();
|
||||||
}
|
}
|
||||||
|
|
||||||
takeSnapshot() {
|
setEmojis(emojis: Array<EmojiPack>) {
|
||||||
return this.#session ? { ...this.#session } : undefined;
|
this.#session.emojis = emojis;
|
||||||
|
this.#save();
|
||||||
|
}
|
||||||
|
|
||||||
|
setMuted(muted: Array<string[]>, ts: number) {
|
||||||
|
if (this.#session.muted.timestamp >= ts) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.#session.muted.tags = muted;
|
||||||
|
this.#session.muted.timestamp = ts;
|
||||||
|
this.#save();
|
||||||
|
}
|
||||||
|
|
||||||
|
setRelays(relays: Array<string>, ts: number) {
|
||||||
|
if (this.#session.relays.timestamp >= ts) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.#session.relays = relays.reduce((acc, r) => {
|
||||||
|
const [, relay] = r;
|
||||||
|
const write = r.length === 2 || r.includes("write");
|
||||||
|
const read = r.length === 2 || r.includes("read");
|
||||||
|
return { ...acc, [relay]: { read, write } };
|
||||||
|
}, {});
|
||||||
|
this.#save();
|
||||||
}
|
}
|
||||||
|
|
||||||
#save() {
|
#save() {
|
||||||
@ -100,47 +131,3 @@ export function getPublisher(session: LoginSession) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setFollows(
|
|
||||||
state: LoginSession,
|
|
||||||
follows: Array<string>,
|
|
||||||
ts: number,
|
|
||||||
) {
|
|
||||||
if (state.follows.timestamp >= ts) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
state.follows.tags = follows;
|
|
||||||
state.follows.timestamp = ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setEmojis(state: LoginSession, emojis: Array<EmojiPack>) {
|
|
||||||
state.emojis = emojis;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setMuted(
|
|
||||||
state: LoginSession,
|
|
||||||
muted: Array<string[]>,
|
|
||||||
ts: number,
|
|
||||||
) {
|
|
||||||
if (state.muted.timestamp >= ts) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
state.muted.tags = muted;
|
|
||||||
state.muted.timestamp = ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setRelays(
|
|
||||||
state: LoginSession,
|
|
||||||
relays: Array<string>,
|
|
||||||
ts: number,
|
|
||||||
) {
|
|
||||||
if (state.relays.timestamp >= ts) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
state.relays = relays.reduce((acc, r) => {
|
|
||||||
const [, relay] = r;
|
|
||||||
const write = r.length === 2 || r.includes("write");
|
|
||||||
const read = r.length === 2 || r.includes("read");
|
|
||||||
return { ...acc, [relay]: { read, write } };
|
|
||||||
}, {});
|
|
||||||
}
|
|
||||||
|
@ -90,3 +90,7 @@ export async function openFile(): Promise<File | undefined> {
|
|||||||
elm.click();
|
elm.click();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getTagValues(tags: Array<string[]>, tag: string) {
|
||||||
|
return tags.filter((t) => t.at(0) === tag).map((t) => t.at(1));
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user