eslint fixes
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Martti Malmi 2024-01-04 13:13:28 +02:00
parent 9f88b44b91
commit eeb6ec9dd8
12 changed files with 93 additions and 54 deletions

View File

@ -17,7 +17,7 @@
"deck": true, "deck": true,
"zapPool": true, "zapPool": true,
"notificationGraph": false, "notificationGraph": false,
"communityLeaders": false "communityLeaders": true
}, },
"signUp": { "signUp": {
"moderation": false, "moderation": false,
@ -27,6 +27,9 @@
"bypassImgProxyError": true, "bypassImgProxyError": true,
"preferLargeMedia": true "preferLargeMedia": true
}, },
"communityLeaders": {
"list": "naddr1qq4xc6tnw3ez6vp58y6rywpjxckngdtyxukngwr9vckkze33vcknzcnrxcenje35xqmn2cczyp3lucccm3v9s087z6qslpkap8schltk427zfgqgrn3g2menq5zw6qcyqqq82vqprpmhxue69uhhyetvv9ujuumwdae8gtnnda3kjctv7rajfl"
},
"noteCreatorToast": false, "noteCreatorToast": false,
"hideFromNavbar": [], "hideFromNavbar": [],
"eventLinkPrefix": "note", "eventLinkPrefix": "note",

View File

@ -25,6 +25,7 @@ class IndexedDB extends Dexie {
super("EventDB"); super("EventDB");
this.version(5).stores({ this.version(5).stores({
// TODO use multientry index for *tags
events: "id, pubkey, kind, created_at, [pubkey+kind]", events: "id, pubkey, kind, created_at, [pubkey+kind]",
tags: "id, eventId, [type+value]", tags: "id, eventId, [type+value]",
}); });
@ -108,40 +109,63 @@ class IndexedDB extends Dexie {
subscribeToAuthors = this._throttle(async function (callback: (event: TaggedNostrEvent) => void, limit?: number) { subscribeToAuthors = this._throttle(async function (callback: (event: TaggedNostrEvent) => void, limit?: number) {
const authors = [...this.subscribedAuthors]; const authors = [...this.subscribedAuthors];
this.subscribedAuthors.clear(); this.subscribedAuthors.clear();
// Start timing
console.time("subscribeToAuthors");
await this.events await this.events
.where("pubkey") .where("pubkey")
.anyOf(authors) .anyOf(authors)
.limit(limit || 1000) .limit(limit || 1000)
.each(callback); .each(callback);
}, 200);
subscribeToEventIds = this._throttle(async function (callback: (event: TaggedNostrEvent) => void) { // End timing and log the elapsed time
console.timeEnd("subscribeToAuthors");
}, 200);
subscribeToEventIds = this._throttle(async function (callback: (event: TaggedNostrEvent) => void) {
const ids = [...this.subscribedEventIds]; const ids = [...this.subscribedEventIds];
this.subscribedEventIds.clear(); this.subscribedEventIds.clear();
await this.events.where("id").anyOf(ids).each(callback);
}, 200);
subscribeToTags = this._throttle(async function (callback: (event: TaggedNostrEvent) => void) { console.time("subscribeToEventIds");
await this.events.where("id").anyOf(ids).each(callback);
console.timeEnd("subscribeToEventIds");
}, 200);
subscribeToTags = this._throttle(async function (callback: (event: TaggedNostrEvent) => void) {
const tagPairs = [...this.subscribedTags].map(tag => tag.split("|")); const tagPairs = [...this.subscribedTags].map(tag => tag.split("|"));
this.subscribedTags.clear(); this.subscribedTags.clear();
console.time("subscribeToTags");
await this.tags await this.tags
.where("[type+value]") .where("[type+value]")
.anyOf(tagPairs) .anyOf(tagPairs)
.each(tag => this.subscribedEventIds.add(tag.eventId)); .each(tag => this.subscribedEventIds.add(tag.eventId));
await this.subscribeToEventIds(callback); await this.subscribeToEventIds(callback);
}, 200);
subscribeToAuthorsAndKinds = this._throttle(async function (callback: (event: TaggedNostrEvent) => void) { console.timeEnd("subscribeToTags");
}, 200);
subscribeToAuthorsAndKinds = this._throttle(async function (callback: (event: TaggedNostrEvent) => void) {
const authorsAndKinds = [...this.subscribedAuthorsAndKinds]; const authorsAndKinds = [...this.subscribedAuthorsAndKinds];
this.subscribedAuthorsAndKinds.clear(); this.subscribedAuthorsAndKinds.clear();
console.time("subscribeToAuthorsAndKinds");
// parse pair[1] as int // parse pair[1] as int
const pairs = authorsAndKinds.map(pair => { const pairs = authorsAndKinds.map(pair => {
const [author, kind] = pair.split("|"); const [author, kind] = pair.split("|");
return [author, parseInt(kind)]; return [author, parseInt(kind)];
}); });
await this.events.where("[pubkey+kind]").anyOf(pairs).each(callback); await this.events.where("[pubkey+kind]").anyOf(pairs).each(callback);
}, 200);
console.timeEnd("subscribeToAuthorsAndKinds");
}, 200);
async find(filter: Filter, callback: (event: TaggedNostrEvent) => void): Promise<void> { async find(filter: Filter, callback: (event: TaggedNostrEvent) => void): Promise<void> {
if (!filter) return; if (!filter) return;

View File

@ -119,7 +119,7 @@ function renderToken(t: Token | Footnotes | Footnote | FootnoteRef, tags: Array<
} }
} }
export const Markdown = forwardRef<HTMLDivElement, MarkdownProps>((props: MarkdownProps, ref) => { const Markdown = forwardRef<HTMLDivElement, MarkdownProps>((props: MarkdownProps, ref) => {
const parsed = useMemo(() => { const parsed = useMemo(() => {
return marked.use(markedFootnote()).lexer(props.content); return marked.use(markedFootnote()).lexer(props.content);
}, [props.content, props.tags]); }, [props.content, props.tags]);
@ -130,4 +130,7 @@ export const Markdown = forwardRef<HTMLDivElement, MarkdownProps>((props: Markdo
</div> </div>
); );
}); });
Markdown.displayName = "Markdown"; Markdown.displayName = "Markdown";
export { Markdown };

View File

@ -325,4 +325,5 @@ const AsyncFooterIcon = forwardRef((props: AsyncIconProps & { value: number }, r
</AsyncIcon> </AsyncIcon>
); );
}); });
AsyncFooterIcon.displayName = "AsyncFooterIcon"; AsyncFooterIcon.displayName = "AsyncFooterIcon";

View File

@ -33,15 +33,6 @@ export default function NoteReaction(props: NoteReactionProps) {
return null; return null;
}, [ev]); }, [ev]);
if (
ev.kind !== EventKind.Reaction &&
ev.kind !== EventKind.Repost &&
(ev.kind !== EventKind.TextNote ||
ev.tags.every((a, i) => a[1] !== refEvent?.[1] || a[3] !== "mention" || ev.content !== `#[${i}]`))
) {
return null;
}
/** /**
* Some clients embed the reposted note in the content * Some clients embed the reposted note in the content
*/ */
@ -63,6 +54,15 @@ export default function NoteReaction(props: NoteReactionProps) {
return props.root; return props.root;
} }
if (
ev.kind !== EventKind.Reaction &&
ev.kind !== EventKind.Repost &&
(ev.kind !== EventKind.TextNote ||
ev.tags.every((a, i) => a[1] !== refEvent?.[1] || a[3] !== "mention" || ev.content !== `#[${i}]`))
) {
return null;
}
if (!inView) { if (!inView) {
return <div className="card reaction" ref={ref}></div>; return <div className="card reaction" ref={ref}></div>;
} }

View File

@ -1,7 +1,12 @@
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
export default function AccountName({ name = "", link = true }) { interface AccountNameProps {
name?: string;
link?: boolean;
}
export default function AccountName({ name = "", link = true }: AccountNameProps) {
const navigate = useNavigate(); const navigate = useNavigate();
return ( return (
<> <>

View File

@ -7,7 +7,12 @@ import { UserCache } from "@/Cache";
import useEventPublisher from "@/Hooks/useEventPublisher"; import useEventPublisher from "@/Hooks/useEventPublisher";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
export default function ActiveAccount({ name = "", setAsPrimary = () => {} }) { interface ActiveAccountProps {
name?: string;
setAsPrimary: () => void;
}
export default function ActiveAccount({ name = "", setAsPrimary = () => {} }: ActiveAccountProps) {
const { publicKey, readonly } = useLogin(s => ({ const { publicKey, readonly } = useLogin(s => ({
publicKey: s.publicKey, publicKey: s.publicKey,
readonly: s.readonly, readonly: s.readonly,

View File

@ -1,7 +1,13 @@
import AccountName from "./AccountName"; import AccountName from "./AccountName";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
export default function ReservedAccount({ name = "", enableReserved = () => {}, declineReserved = () => {} }) { interface ReservedAccountProps {
name?: string;
enableReserved: () => void;
declineReserved: () => void;
}
export default function ReservedAccount({ name = "", enableReserved = () => {}, declineReserved = () => {} }: ReservedAccountProps) {
return ( return (
<div> <div>
<p className="success"> <p className="success">

View File

@ -1,19 +1,13 @@
import { LoginSession, LoginStore } from "@/Login"; import { LoginSession, LoginStore } from "@/Login";
import { useSyncExternalStore } from "react";
import { useSyncExternalStoreWithSelector } from "use-sync-external-store/with-selector"; import { useSyncExternalStoreWithSelector } from "use-sync-external-store/with-selector";
export default function useLogin<T = LoginSession>(selector?: (v: LoginSession) => T) { export default function useLogin<T = LoginSession>(selector?: (v: LoginSession) => T) {
if (selector) { const defaultSelector = (v: LoginSession) => v as unknown as T;
return useSyncExternalStoreWithSelector(
s => LoginStore.hook(s), return useSyncExternalStoreWithSelector<LoginSession, T>(
() => LoginStore.snapshot(), s => LoginStore.hook(s),
undefined, () => LoginStore.snapshot(),
selector, undefined,
); selector || defaultSelector,
} else { );
return useSyncExternalStore<T>(
s => LoginStore.hook(s),
() => LoginStore.snapshot() as T,
);
}
} }

View File

@ -26,9 +26,7 @@ export default function Index() {
useTheme(); useTheme();
useLoginRelays(); useLoginRelays();
useLoginFeed(); useLoginFeed();
if (CONFIG.features.communityLeaders) { useCommunityLeaders();
useCommunityLeaders();
}
const hideHeaderPaths = ["/login", "/new"]; const hideHeaderPaths = ["/login", "/new"];
const shouldHideFooter = location.pathname.startsWith("/messages/"); const shouldHideFooter = location.pathname.startsWith("/messages/");

View File

@ -6,7 +6,13 @@ import { subscribeToNotifications } from "@/Notifications";
import useEventPublisher from "@/Hooks/useEventPublisher"; import useEventPublisher from "@/Hooks/useEventPublisher";
import messages from "./messages"; import messages from "./messages";
const StatusIndicator = ({ status, enabledMessage, disabledMessage }) => { interface StatusIndicatorProps {
status: boolean;
enabledMessage: React.ComponentProps<typeof FormattedMessage>;
disabledMessage: React.ComponentProps<typeof FormattedMessage>;
}
const StatusIndicator = ({ status, enabledMessage, disabledMessage }: StatusIndicatorProps) => {
return status ? ( return status ? (
<div className="flex items-center"> <div className="flex items-center">
<Icon name="check" size={20} className="text-green-500 mr-2" /> <Icon name="check" size={20} className="text-green-500 mr-2" />

View File

@ -1,7 +1,6 @@
import { ExternalStore } from "@snort/shared"; import { ExternalStore } from "@snort/shared";
import { NostrEvent, TaggedNostrEvent } from "@snort/system"; import { NostrEvent, TaggedNostrEvent } from "@snort/system";
import { ZapTarget } from "@/Zapper"; import { ZapTarget } from "@/Zapper";
import { useSyncExternalStore } from "react";
import { useSyncExternalStoreWithSelector } from "use-sync-external-store/with-selector"; import { useSyncExternalStoreWithSelector } from "use-sync-external-store/with-selector";
interface NoteCreatorDataSnapshot { interface NoteCreatorDataSnapshot {
@ -90,17 +89,12 @@ const NoteCreatorState = new NoteCreatorStore();
export function useNoteCreator<T extends object = NoteCreatorDataSnapshot>( export function useNoteCreator<T extends object = NoteCreatorDataSnapshot>(
selector?: (v: NoteCreatorDataSnapshot) => T, selector?: (v: NoteCreatorDataSnapshot) => T,
) { ) {
if (selector) { const defaultSelector = (v: NoteCreatorDataSnapshot) => v as unknown as T;
return useSyncExternalStoreWithSelector<NoteCreatorDataSnapshot, T>(
c => NoteCreatorState.hook(c), return useSyncExternalStoreWithSelector<NoteCreatorDataSnapshot, T>(
() => NoteCreatorState.snapshot(), c => NoteCreatorState.hook(c),
undefined, () => NoteCreatorState.snapshot(),
selector, undefined,
); selector || defaultSelector,
} else { );
return useSyncExternalStore<T>(
c => NoteCreatorState.hook(c),
() => NoteCreatorState.snapshot() as T,
);
}
} }