mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-17 21:31:43 +01:00
code cleanup
This commit is contained in:
parent
f94a3450eb
commit
4e7e856b95
@ -11,9 +11,9 @@
|
||||
"start": "vite serve",
|
||||
"dev": "VITE_APP_VERSION=dev vite serve",
|
||||
"build": "tsc --project tsconfig.json && vite build",
|
||||
"format": "prettier --ignore-path .prettierignore -w .",
|
||||
"build-icons": "node ./scripts/build-icons.mjs",
|
||||
"analyze": "pnpm dlx vite-bundle-visualizer -o ./stats.html",
|
||||
"build-icons": "node ./scripts/build-icons.mjs"
|
||||
"format": "prettier --ignore-path .prettierignore -w ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@cashu/cashu-ts": "2.0.0-rc1",
|
||||
|
@ -73,7 +73,7 @@ export default class ChunkedRequest {
|
||||
}
|
||||
|
||||
let filters: Filter[] = mergeFilter(this.filters, { limit: this.chunkSize });
|
||||
let oldestEvent = this.getLastEvent();
|
||||
const oldestEvent = this.getLastEvent();
|
||||
if (oldestEvent) {
|
||||
filters = mergeFilter(filters, { until: oldestEvent.created_at - 1 });
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ export class PubkeyGraph extends EventEmitter<EventMap> {
|
||||
const refCount = new Map<string, number>();
|
||||
const walkLevel = (level = 0) => {
|
||||
if (next.size === 0) return;
|
||||
let keys = new Set(next);
|
||||
const keys = new Set(next);
|
||||
next.clear();
|
||||
|
||||
for (const key of keys) {
|
||||
@ -141,7 +141,7 @@ export class PubkeyGraph extends EventEmitter<EventMap> {
|
||||
}
|
||||
|
||||
getPaths(pubkey: string, maxLength = 2) {
|
||||
let paths: string[][] = [];
|
||||
const paths: string[][] = [];
|
||||
|
||||
const walk = (p: string, maxLvl = 0, path: string[] = []) => {
|
||||
if (path.includes(p)) return;
|
||||
|
@ -106,7 +106,7 @@ export default class RelayPool implements IConnectionPool {
|
||||
}
|
||||
|
||||
async waitForOpen(relayOrUrl: string | URL | AbstractRelay, quite = true) {
|
||||
let relay = this.getRelay(relayOrUrl);
|
||||
const relay = this.getRelay(relayOrUrl);
|
||||
if (!relay) return Promise.reject("Missing relay");
|
||||
|
||||
if (relay.connected) return true;
|
||||
@ -123,7 +123,7 @@ export default class RelayPool implements IConnectionPool {
|
||||
}
|
||||
|
||||
async requestConnect(relayOrUrl: string | URL | AbstractRelay, quite = true) {
|
||||
let relay = this.getRelay(relayOrUrl);
|
||||
const relay = this.getRelay(relayOrUrl);
|
||||
if (!relay) return;
|
||||
|
||||
if (!relay.connected && !offlineMode.value) {
|
||||
@ -144,11 +144,11 @@ export default class RelayPool implements IConnectionPool {
|
||||
}
|
||||
|
||||
getRelayAuthStorageKey(relayOrUrl: string | URL | AbstractRelay) {
|
||||
let relay = this.getRelay(relayOrUrl);
|
||||
const relay = this.getRelay(relayOrUrl);
|
||||
return `${relay!.url}-auth-mode`;
|
||||
}
|
||||
getRelayAuthMode(relayOrUrl: string | URL | AbstractRelay): RelayAuthMode | undefined {
|
||||
let relay = this.getRelay(relayOrUrl);
|
||||
const relay = this.getRelay(relayOrUrl);
|
||||
if (!relay) return;
|
||||
|
||||
const defaultMode = localSettings.defaultAuthenticationMode.value;
|
||||
@ -157,7 +157,7 @@ export default class RelayPool implements IConnectionPool {
|
||||
return mode || defaultMode;
|
||||
}
|
||||
setRelayAuthMode(relayOrUrl: string | URL | AbstractRelay, mode: RelayAuthMode) {
|
||||
let relay = this.getRelay(relayOrUrl);
|
||||
const relay = this.getRelay(relayOrUrl);
|
||||
if (!relay) return;
|
||||
|
||||
localStorage.setItem(this.getRelayAuthStorageKey(relay), mode);
|
||||
@ -169,7 +169,7 @@ export default class RelayPool implements IConnectionPool {
|
||||
sign: Parameters<AbstractRelay["auth"]>[0],
|
||||
quite = true,
|
||||
) {
|
||||
let relay = this.getRelay(relayOrUrl);
|
||||
const relay = this.getRelay(relayOrUrl);
|
||||
if (!relay) return;
|
||||
|
||||
const pending = this.pendingAuth.get(relay);
|
||||
@ -204,7 +204,7 @@ export default class RelayPool implements IConnectionPool {
|
||||
}
|
||||
|
||||
canSubscribe(relayOrUrl: string | URL | AbstractRelay) {
|
||||
let relay = this.getRelay(relayOrUrl);
|
||||
const relay = this.getRelay(relayOrUrl);
|
||||
if (!relay) return false;
|
||||
|
||||
return this.authForSubscribe.get(relay).value !== false;
|
||||
|
@ -270,7 +270,7 @@ export default class NostrWebRTCPeer extends EventEmitter<EventMap> {
|
||||
|
||||
this.log(`Got ${candidates.length} candidates`);
|
||||
|
||||
for (let candidate of candidates) {
|
||||
for (const candidate of candidates) {
|
||||
await pc.addIceCandidate(candidate);
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ export default class WebRtcRelayServer extends EventEmitter<EventMap> {
|
||||
handleCloseMessage(data: any[]) {
|
||||
const [_, id] = data as [string, string, ...Filter[]];
|
||||
|
||||
let sub = this.subscriptions.get(id);
|
||||
const sub = this.subscriptions.get(id);
|
||||
if (sub) {
|
||||
sub.close();
|
||||
this.subscriptions.delete(id);
|
||||
|
@ -49,7 +49,7 @@ export function renderYoutubePlaylistURL(match: URL) {
|
||||
|
||||
function YoutubeVideoEmbed({ url }: { url: URL }) {
|
||||
const { youtubeRedirect } = useAppSettings();
|
||||
var videoId = url.searchParams.get("v");
|
||||
let videoId = url.searchParams.get("v");
|
||||
if (url.hostname === "youtu.be") videoId = url.pathname.split("/")[1];
|
||||
if (!videoId) return null;
|
||||
|
||||
@ -74,7 +74,7 @@ export function renderYoutubeVideoURL(match: URL) {
|
||||
if (!YOUTUBE_DOMAINS.includes(match.hostname)) return null;
|
||||
if (match.pathname.startsWith("/live")) return null;
|
||||
|
||||
var videoId = match.searchParams.get("v");
|
||||
let videoId = match.searchParams.get("v");
|
||||
if (match.hostname === "youtu.be") videoId = match.pathname.split("/")[1];
|
||||
if (!videoId) return null;
|
||||
|
||||
|
@ -10,7 +10,7 @@ export default function DebugEventCachePage({ event }: { event: NostrEvent }) {
|
||||
const update = () => eventStore.update(event);
|
||||
|
||||
const renderValue = (field: symbol) => {
|
||||
let value = Reflect.get(event, field);
|
||||
const value = Reflect.get(event, field);
|
||||
|
||||
if (value instanceof Map) return JSON.stringify(Object.fromEntries(value.entries()));
|
||||
if (value instanceof Set) return JSON.stringify(Array.from(value));
|
||||
|
@ -44,7 +44,7 @@ function TimelineItem({ event }: { event: NostrEvent }) {
|
||||
|
||||
const renderContent = () => {
|
||||
switch (event.kind) {
|
||||
case kinds.EncryptedDirectMessage:
|
||||
case kinds.EncryptedDirectMessage: {
|
||||
const sender = getDMSender(event);
|
||||
const recipient = getDMRecipient(event);
|
||||
return (
|
||||
@ -52,13 +52,15 @@ function TimelineItem({ event }: { event: NostrEvent }) {
|
||||
<UserName pubkey={sender} fontWeight="bold" /> messaged <UserName pubkey={recipient} fontWeight="bold" />
|
||||
</Text>
|
||||
);
|
||||
case kinds.Contacts:
|
||||
}
|
||||
case kinds.Contacts: {
|
||||
return (
|
||||
<Text noOfLines={1} isTruncated>
|
||||
Updated contacts
|
||||
</Text>
|
||||
);
|
||||
case kinds.Reaction:
|
||||
}
|
||||
case kinds.Reaction: {
|
||||
const pointer = nip25.getReactedEventPointer(event);
|
||||
return (
|
||||
<HoverLinkOverlay
|
||||
@ -70,12 +72,14 @@ function TimelineItem({ event }: { event: NostrEvent }) {
|
||||
{event.content}
|
||||
</HoverLinkOverlay>
|
||||
);
|
||||
default:
|
||||
}
|
||||
default: {
|
||||
return (
|
||||
<HoverLinkOverlay as={RouterLink} to={`/l/${getSharableEventAddress(event)}`} noOfLines={1} isTruncated>
|
||||
{event.content}
|
||||
</HoverLinkOverlay>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -135,4 +135,6 @@ const MagicTextArea = forwardRef<HTMLTextAreaElement, TextareaProps & { instance
|
||||
},
|
||||
);
|
||||
|
||||
MagicTextArea.displayName = "MagicTextArea";
|
||||
|
||||
export { MagicInput, MagicTextArea as default };
|
||||
|
@ -9,7 +9,6 @@ import StreamNote from "./stream-note";
|
||||
import RelayRecommendation from "./relay-recommendation";
|
||||
import BadgeAwardCard from "../../../views/badges/components/badge-award-card";
|
||||
import { isReply } from "../../../helpers/nostr/event";
|
||||
import { STREAM_KIND } from "../../../helpers/nostr/stream";
|
||||
import { NostrEvent } from "../../../types/nostr-event";
|
||||
import { FLARE_VIDEO_KIND } from "../../../helpers/nostr/video";
|
||||
import EmbeddedFlareVideo from "../../embed-event/event-types/embedded-flare-video";
|
||||
|
@ -37,13 +37,13 @@ function ImageGallery({ images }: { images: PhotoWithEvent[] }) {
|
||||
|
||||
export default function MediaTimeline({ timeline }: { timeline: NostrEvent[] }) {
|
||||
const images = useMemo(() => {
|
||||
var images: PhotoWithEvent[] = [];
|
||||
const images: PhotoWithEvent[] = [];
|
||||
|
||||
for (const event of timeline) {
|
||||
if (event.kind === kinds.Repost || event.kind === kinds.GenericRepost) continue;
|
||||
const urls = event.content.matchAll(getMatchLink());
|
||||
|
||||
let i = 0;
|
||||
const i = 0;
|
||||
for (const match of urls) {
|
||||
if (isImageURL(match[0])) images.push({ event, src: match[0] });
|
||||
}
|
||||
|
@ -121,14 +121,14 @@ export function UserFollowButton({ pubkey, showLists, ...props }: UserFollowButt
|
||||
const signed = await requestSignature(draft);
|
||||
await publish("Follow", signed);
|
||||
setLoading(false);
|
||||
}, [contacts, requestSignature]);
|
||||
}, [contacts, requestSignature, pubkey, publish]);
|
||||
const handleUnfollow = useAsyncErrorHandler(async () => {
|
||||
setLoading(true);
|
||||
const draft = listRemovePerson(contacts || createEmptyContactList(), pubkey);
|
||||
const signed = await requestSignature(draft);
|
||||
await publish("Unfollow", signed);
|
||||
setLoading(false);
|
||||
}, [contacts, requestSignature]);
|
||||
}, [contacts, requestSignature, pubkey, publish]);
|
||||
|
||||
if (showLists) {
|
||||
return (
|
||||
|
@ -1,7 +1,7 @@
|
||||
// based on https://stackoverflow.com/a/10469752
|
||||
export function humanReadableSats(sats: number) {
|
||||
if (sats === 0) return "0";
|
||||
var s = ["", "K", "M"];
|
||||
var e = Math.floor(Math.log(sats) / Math.log(1000));
|
||||
const s = ["", "K", "M"];
|
||||
const e = Math.floor(Math.log(sats) / Math.log(1000));
|
||||
return Math.round((sats / Math.pow(1000, e)) * 100) / 100 + s[e];
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ export function getContentTagRefs(content: string, tags: Tag[]) {
|
||||
break;
|
||||
}
|
||||
|
||||
let matchingTags = tags.filter((t) => t[0] === type && t[1] === id);
|
||||
const matchingTags = tags.filter((t) => t[0] === type && t[1] === id);
|
||||
for (const t of matchingTags) foundTags.add(t);
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ import { cloneEvent } from "./event";
|
||||
|
||||
/** fixes or removes any bad r tags */
|
||||
export function cleanRTags(tags: Tag[]) {
|
||||
let newTags: Tag[] = [];
|
||||
const newTags: Tag[] = [];
|
||||
for (const tag of tags) {
|
||||
if (tag[0] === "r") {
|
||||
if (!tag[1]) continue;
|
||||
@ -39,7 +39,7 @@ export function getRelaysFromMailbox(list: NostrEvent | DraftNostrEvent): { url:
|
||||
}
|
||||
|
||||
export function addRelayModeToMailbox(list: NostrEvent | undefined, relay: string, mode: RelayMode): DraftNostrEvent {
|
||||
let draft = cloneEvent(kinds.RelayList, list);
|
||||
const draft = cloneEvent(kinds.RelayList, list);
|
||||
draft.tags = cleanRTags(draft.tags);
|
||||
|
||||
const existing = draft.tags.find((t) => t[0] === "r" && t[1] === relay) as RTag;
|
||||
@ -54,7 +54,7 @@ export function removeRelayModeFromMailbox(
|
||||
relay: string,
|
||||
mode: RelayMode,
|
||||
): DraftNostrEvent {
|
||||
let draft = cloneEvent(kinds.RelayList, list);
|
||||
const draft = cloneEvent(kinds.RelayList, list);
|
||||
draft.tags = cleanRTags(draft.tags);
|
||||
|
||||
const existing = draft.tags.find((t) => t[0] === "r" && t[1] === relay) as RTag;
|
||||
|
@ -6,20 +6,20 @@ import { getZapPayment, isETag, isPTag, ProfileContent } from "applesauce-core/h
|
||||
export async function getZapEndpoint(metadata: ProfileContent): Promise<null | string> {
|
||||
try {
|
||||
let lnurl: string = "";
|
||||
let { lud06, lud16 } = metadata;
|
||||
const { lud06, lud16 } = metadata;
|
||||
if (lud06) {
|
||||
let { words } = bech32.decode(lud06 as `${string}1${string}`, 1000);
|
||||
let data = bech32.fromWords(words);
|
||||
const { words } = bech32.decode(lud06 as `${string}1${string}`, 1000);
|
||||
const data = bech32.fromWords(words);
|
||||
lnurl = utils.utf8Decoder.decode(data);
|
||||
} else if (lud16) {
|
||||
let [name, domain] = lud16.split("@");
|
||||
const [name, domain] = lud16.split("@");
|
||||
lnurl = `https://${domain}/.well-known/lnurlp/${name}`;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
let res = await fetch(lnurl);
|
||||
let body = await res.json();
|
||||
const res = await fetch(lnurl);
|
||||
const body = await res.json();
|
||||
|
||||
if (body.allowsNostr && body.nostrPubkey) {
|
||||
return body.callback;
|
||||
|
@ -2,7 +2,7 @@ import { QrCode } from "../lib/qrcodegen";
|
||||
|
||||
export function drawSvgPath(qr: QrCode, border: number): string {
|
||||
if (border < 0) throw new RangeError("Border must be non-negative");
|
||||
let parts: Array<string> = [];
|
||||
const parts: Array<string> = [];
|
||||
for (let y = 0; y < qr.size; y++) {
|
||||
for (let x = 0; x < qr.size; x++) {
|
||||
if (qr.getModule(x, y)) parts.push(`M${x + border},${y + border}h1v1h-1z`);
|
||||
|
@ -151,7 +151,7 @@ export function subscribeMany(relays: string[], filters: Filter[], params: Subsc
|
||||
return;
|
||||
}
|
||||
|
||||
let subscription = relay.subscribe(filters, {
|
||||
const subscription = relay.subscribe(filters, {
|
||||
...params,
|
||||
oneose: () => handleEose(i),
|
||||
onclose: (reason) => handleClose(i, reason),
|
||||
|
@ -12,7 +12,7 @@ export type NumberCache = {
|
||||
export default function useNumberCache(cacheKey: string): NumberCache {
|
||||
const get = useCallback(
|
||||
(key: string) => {
|
||||
let map = cache.get(cacheKey);
|
||||
const map = cache.get(cacheKey);
|
||||
if (!map) return undefined;
|
||||
|
||||
return map.get(key);
|
||||
|
@ -99,7 +99,7 @@ export function mediaSetup(ogObject: OgObjectInteral) {
|
||||
ogObject.ogImageURL = ogObject.ogImageURL ? ogObject.ogImageURL : [];
|
||||
ogObject.ogImageProperty = ogObject.ogImageProperty ? ogObject.ogImageProperty : [];
|
||||
// set ogImageProperty to ogImageSecureURL if it exists
|
||||
// eslint-disable-next-line max-len
|
||||
|
||||
ogObject.ogImageProperty =
|
||||
ogObject.ogImageSecureURL.length !== 0 ? ogObject.ogImageSecureURL : ogObject.ogImageProperty;
|
||||
// fall back to ogImageURL if ogImageProperty isn't set
|
||||
@ -150,7 +150,7 @@ export function mediaSetup(ogObject: OgObjectInteral) {
|
||||
ogObject.twitterImageAlt
|
||||
) {
|
||||
ogObject.twitterImageSrc = ogObject.twitterImageSrc ? ogObject.twitterImageSrc : [];
|
||||
// eslint-disable-next-line max-len
|
||||
|
||||
ogObject.twitterImageProperty = ogObject.twitterImageProperty
|
||||
? ogObject.twitterImageProperty
|
||||
: ogObject.twitterImageSrc; // deafult to twitterImageSrc
|
||||
|
@ -114,7 +114,7 @@ export class QrCode {
|
||||
}
|
||||
|
||||
// Concatenate all segments to create the data bit string
|
||||
let bb: Array<bit> = [];
|
||||
const bb: Array<bit> = [];
|
||||
for (const seg of segs) {
|
||||
appendBits(seg.mode.modeBits, 4, bb);
|
||||
appendBits(seg.numChars, seg.mode.numCharCountBits(version), bb);
|
||||
@ -133,7 +133,7 @@ export class QrCode {
|
||||
for (let padByte = 0xec; bb.length < dataCapacityBits; padByte ^= 0xec ^ 0x11) appendBits(padByte, 8, bb);
|
||||
|
||||
// Pack bits into bytes in big endian
|
||||
let dataCodewords: Array<byte> = [];
|
||||
const dataCodewords: Array<byte> = [];
|
||||
while (dataCodewords.length * 8 < bb.length) dataCodewords.push(0);
|
||||
bb.forEach((b: bit, i: int) => (dataCodewords[i >>> 3] |= b << (7 - (i & 7))));
|
||||
|
||||
@ -184,7 +184,7 @@ export class QrCode {
|
||||
this.size = version * 4 + 17;
|
||||
|
||||
// Initialize both grids to be size*size arrays of Boolean false
|
||||
let row: Array<boolean> = [];
|
||||
const row: Array<boolean> = [];
|
||||
for (let i = 0; i < this.size; i++) row.push(false);
|
||||
for (let i = 0; i < this.size; i++) {
|
||||
this.modules.push(row.slice()); // Initially all light
|
||||
@ -350,10 +350,10 @@ export class QrCode {
|
||||
const shortBlockLen: int = Math.floor(rawCodewords / numBlocks);
|
||||
|
||||
// Split data into blocks and append ECC to each block
|
||||
let blocks: Array<Array<byte>> = [];
|
||||
const blocks: Array<Array<byte>> = [];
|
||||
const rsDiv: Array<byte> = QrCode.reedSolomonComputeDivisor(blockEccLen);
|
||||
for (let i = 0, k = 0; i < numBlocks; i++) {
|
||||
let dat: Array<byte> = data.slice(k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1));
|
||||
const dat: Array<byte> = data.slice(k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1));
|
||||
k += dat.length;
|
||||
const ecc: Array<byte> = QrCode.reedSolomonComputeRemainder(dat, rsDiv);
|
||||
if (i < numShortBlocks) dat.push(0);
|
||||
@ -361,7 +361,7 @@ export class QrCode {
|
||||
}
|
||||
|
||||
// Interleave (not concatenate) the bytes from every block into a single sequence
|
||||
let result: Array<byte> = [];
|
||||
const result: Array<byte> = [];
|
||||
for (let i = 0; i < blocks[0].length; i++) {
|
||||
blocks.forEach((block, j) => {
|
||||
// Skip the padding byte in short blocks
|
||||
@ -452,7 +452,7 @@ export class QrCode {
|
||||
for (let y = 0; y < this.size; y++) {
|
||||
let runColor = false;
|
||||
let runX = 0;
|
||||
let runHistory = [0, 0, 0, 0, 0, 0, 0];
|
||||
const runHistory = [0, 0, 0, 0, 0, 0, 0];
|
||||
for (let x = 0; x < this.size; x++) {
|
||||
if (this.modules[y][x] == runColor) {
|
||||
runX++;
|
||||
@ -471,7 +471,7 @@ export class QrCode {
|
||||
for (let x = 0; x < this.size; x++) {
|
||||
let runColor = false;
|
||||
let runY = 0;
|
||||
let runHistory = [0, 0, 0, 0, 0, 0, 0];
|
||||
const runHistory = [0, 0, 0, 0, 0, 0, 0];
|
||||
for (let y = 0; y < this.size; y++) {
|
||||
if (this.modules[y][x] == runColor) {
|
||||
runY++;
|
||||
@ -518,7 +518,7 @@ export class QrCode {
|
||||
else {
|
||||
const numAlign: int = Math.floor(this.version / 7) + 2;
|
||||
const step: int = this.version == 32 ? 26 : Math.ceil((this.version * 4 + 4) / (numAlign * 2 - 2)) * 2;
|
||||
let result: Array<int> = [6];
|
||||
const result: Array<int> = [6];
|
||||
for (let pos = this.size - 7; result.length < numAlign; pos -= step) result.splice(1, 0, pos);
|
||||
return result;
|
||||
}
|
||||
@ -555,7 +555,7 @@ export class QrCode {
|
||||
if (degree < 1 || degree > 255) throw new RangeError("Degree out of range");
|
||||
// Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.
|
||||
// For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array [255, 8, 93].
|
||||
let result: Array<byte> = [];
|
||||
const result: Array<byte> = [];
|
||||
for (let i = 0; i < degree - 1; i++) result.push(0);
|
||||
result.push(1); // Start off with the monomial x^0
|
||||
|
||||
@ -576,7 +576,7 @@ export class QrCode {
|
||||
|
||||
// Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials.
|
||||
private static reedSolomonComputeRemainder(data: Readonly<Array<byte>>, divisor: Readonly<Array<byte>>): Array<byte> {
|
||||
let result: Array<byte> = divisor.map((_) => 0);
|
||||
const result: Array<byte> = divisor.map((_) => 0);
|
||||
for (const b of data) {
|
||||
// Polynomial division
|
||||
const factor: byte = b ^ (result.shift() as byte);
|
||||
@ -730,7 +730,7 @@ export class QrSegment {
|
||||
// byte mode. All input byte arrays are acceptable. Any text string
|
||||
// can be converted to UTF-8 bytes and encoded as a byte mode segment.
|
||||
public static makeBytes(data: Readonly<Array<byte>>): QrSegment {
|
||||
let bb: Array<bit> = [];
|
||||
const bb: Array<bit> = [];
|
||||
for (const b of data) appendBits(b, 8, bb);
|
||||
return new QrSegment(Mode.BYTE, data.length, bb);
|
||||
}
|
||||
@ -738,7 +738,7 @@ export class QrSegment {
|
||||
// Returns a segment representing the given string of decimal digits encoded in numeric mode.
|
||||
public static makeNumeric(digits: string): QrSegment {
|
||||
if (!QrSegment.isNumeric(digits)) throw new RangeError("String contains non-numeric characters");
|
||||
let bb: Array<bit> = [];
|
||||
const bb: Array<bit> = [];
|
||||
for (let i = 0; i < digits.length; ) {
|
||||
// Consume up to 3 digits per iteration
|
||||
const n: int = Math.min(digits.length - i, 3);
|
||||
@ -754,7 +754,7 @@ export class QrSegment {
|
||||
public static makeAlphanumeric(text: string): QrSegment {
|
||||
if (!QrSegment.isAlphanumeric(text))
|
||||
throw new RangeError("String contains unencodable characters in alphanumeric mode");
|
||||
let bb: Array<bit> = [];
|
||||
const bb: Array<bit> = [];
|
||||
let i: int;
|
||||
for (i = 0; i + 2 <= text.length; i += 2) {
|
||||
// Process groups of 2
|
||||
@ -781,7 +781,7 @@ export class QrSegment {
|
||||
// Returns a segment representing an Extended Channel Interpretation
|
||||
// (ECI) designator with the given assignment value.
|
||||
public static makeEci(assignVal: int): QrSegment {
|
||||
let bb: Array<bit> = [];
|
||||
const bb: Array<bit> = [];
|
||||
if (assignVal < 0) throw new RangeError("ECI assignment value out of range");
|
||||
else if (assignVal < 1 << 7) appendBits(assignVal, 8, bb);
|
||||
else if (assignVal < 1 << 14) {
|
||||
@ -850,7 +850,7 @@ export class QrSegment {
|
||||
// Returns a new array of bytes representing the given string encoded in UTF-8.
|
||||
private static toUtf8ByteArray(str: string): Array<byte> {
|
||||
str = encodeURI(str);
|
||||
let result: Array<byte> = [];
|
||||
const result: Array<byte> = [];
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
if (str.charAt(i) != "%") result.push(str.charCodeAt(i));
|
||||
else {
|
||||
|
@ -65,7 +65,7 @@ export default function NotificationsProvider({ children }: PropsWithChildren) {
|
||||
const n = new AccountNotifications(account.pubkey);
|
||||
setNotifications(n);
|
||||
if (import.meta.env.DEV) {
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error debug
|
||||
window.accountNotifications = n;
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ export default function PublishProvider({ children }: PropsWithChildren) {
|
||||
if (!Object.hasOwn(event, "pubkey")) event = await finalizeDraft(event);
|
||||
|
||||
// sign event
|
||||
let signed = !Object.hasOwn(event, "sig") ? await requestSignature(event) : (event as NostrEvent);
|
||||
const signed = !Object.hasOwn(event, "sig") ? await requestSignature(event) : (event as NostrEvent);
|
||||
|
||||
const pub = new PublishAction(label, relays, signed);
|
||||
setLog((arr) => arr.concat(pub));
|
||||
|
@ -75,7 +75,7 @@ export default function WebOfTrustProvider({ pubkey, children }: PropsWithChildr
|
||||
if (!graph) return;
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
//@ts-expect-error
|
||||
//@ts-expect-error debug
|
||||
window.webOfTrust = graph;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ import accountService from "../../services/account";
|
||||
import { deleteDatabase } from "../../services/db";
|
||||
|
||||
export default function RequireCurrentAccount({ children }: { children: JSX.Element }) {
|
||||
let location = useLocation();
|
||||
const location = useLocation();
|
||||
const loading = useObservable(accountService.loading);
|
||||
const account = useObservable(accountService.current);
|
||||
|
||||
|
@ -28,7 +28,7 @@ export default function TrustedMintsQuery(pubkey: string): Query<TrustedMints |
|
||||
|
||||
case "relay":
|
||||
if (tag[1]) {
|
||||
let safe = safeRelayUrl(tag[1]);
|
||||
const safe = safeRelayUrl(tag[1]);
|
||||
if (safe) mints.push(safe);
|
||||
}
|
||||
break;
|
||||
|
@ -161,7 +161,7 @@ class AccountService {
|
||||
const accountService = new AccountService();
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error debug
|
||||
window.accountService = accountService;
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,7 @@ class ChannelMetadataService {
|
||||
const channelMetadataService = new ChannelMetadataService();
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
//@ts-ignore
|
||||
//@ts-expect-error debug
|
||||
window.channelMetadataService = channelMetadataService;
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ class DecryptionCache {
|
||||
const decryptionCacheService = new DecryptionCache();
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error debug
|
||||
window.decryptionCacheService = decryptionCacheService;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ class DictionaryService {
|
||||
const dictionaryService = new DictionaryService(eventStore);
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error debug
|
||||
window.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
|
@ -155,7 +155,7 @@ setInterval(() => {
|
||||
}, 1000 * 60);
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error debug
|
||||
window.dnsIdentityService = dnsIdentityService;
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ class EventCountService {
|
||||
const eventCountService = new EventCountService();
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error debug
|
||||
window.eventCountService = eventCountService;
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ class EventReactionsService {
|
||||
const eventReactionsService = new EventReactionsService();
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error debug
|
||||
window.eventReactionsService = eventReactionsService;
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,8 @@ export const eventStore = new EventStore();
|
||||
export const queryStore = new QueryStore(eventStore);
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error debug
|
||||
window.eventStore = eventStore;
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error debug
|
||||
window.queryStore = queryStore;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ class EventZapsService {
|
||||
const eventZapsService = new EventZapsService();
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error debug
|
||||
window.eventZapsService = eventZapsService;
|
||||
}
|
||||
|
||||
|
@ -109,8 +109,8 @@ setInterval(() => {
|
||||
}, 60_000);
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
//@ts-ignore
|
||||
//@ts-expect-error debug
|
||||
window.localDatabase = localDatabase;
|
||||
//@ts-ignore
|
||||
//@ts-expect-error debug
|
||||
window.localRelay = localRelay;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ const localSettings = {
|
||||
};
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error debug
|
||||
window.localSettings = localSettings;
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,6 @@ const noStrudel = {
|
||||
|
||||
localSettings.debugApi.subscribe((enabled) => {
|
||||
if (enabled) Reflect.set(window, "noStrudel", noStrudel);
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error debug
|
||||
else delete window.noStrudel;
|
||||
});
|
||||
|
@ -40,7 +40,7 @@ class ProcessManager {
|
||||
const processManager = new ProcessManager();
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error debug
|
||||
window.processManager = processManager;
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ const readStatusService = new ReadStatusService();
|
||||
setInterval(readStatusService.prune.bind(readStatusService), 30_000);
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error debug
|
||||
window.readStatusService = readStatusService;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ if (localRelay instanceof AbstractRelay) {
|
||||
}
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error debug
|
||||
window.relayPoolService = relayPoolService;
|
||||
}
|
||||
|
||||
|
@ -264,7 +264,7 @@ setInterval(() => {
|
||||
}, 1000 * 30);
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error debug
|
||||
window.relayScoreboardService = relayScoreboardService;
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,7 @@ class RelayStatsService {
|
||||
const relayStatsService = new RelayStatsService();
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
//@ts-ignore
|
||||
//@ts-expect-error debug
|
||||
window.relayStatsService = relayStatsService;
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ class ReplaceableEventsService {
|
||||
const replaceableEventsService = new ReplaceableEventsService(eventStore);
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
//@ts-ignore
|
||||
//@ts-expect-error debug
|
||||
window.replaceableEventsService = replaceableEventsService;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ const updates = eventStore.stream([{ kinds: [kinds.Metadata] }]).pipe(
|
||||
|
||||
const updates: UserDirectory = {};
|
||||
const transaction = db.transaction("userSearch", "readwrite");
|
||||
for (let metadata of events) {
|
||||
for (const metadata of events) {
|
||||
const profile = getProfileContent(metadata);
|
||||
const names = getSearchNames(profile);
|
||||
updates[metadata.pubkey] = names;
|
||||
|
@ -13,7 +13,7 @@ export default function CommunityModList({
|
||||
return (
|
||||
<AvatarGroup {...props}>
|
||||
{mods.map((pubkey) => (
|
||||
<UserAvatarLink pubkey={pubkey} />
|
||||
<UserAvatarLink key={pubkey} pubkey={pubkey} />
|
||||
))}
|
||||
</AvatarGroup>
|
||||
);
|
||||
|
@ -72,7 +72,7 @@ export default function HorizontalCommunityDetails({
|
||||
</Heading>
|
||||
<Flex direction="column" gap="2">
|
||||
{mods.map((pubkey) => (
|
||||
<Flex gap="2">
|
||||
<Flex key={pubkey} gap="2">
|
||||
<UserAvatarLink pubkey={pubkey} size="xs" />
|
||||
<UserLink pubkey={pubkey} />
|
||||
</Flex>
|
||||
@ -117,7 +117,7 @@ export default function HorizontalCommunityDetails({
|
||||
</Heading>
|
||||
<Box>
|
||||
{links.map(([url, name]) => (
|
||||
<Link href={url} isTruncated isExternal display="block">
|
||||
<Link key={url + name} href={url} isTruncated isExternal display="block">
|
||||
{name || url}
|
||||
</Link>
|
||||
))}
|
||||
|
@ -54,7 +54,7 @@ export default function VerticalCommunityDetails({
|
||||
</Heading>
|
||||
<Flex direction="column" gap="2">
|
||||
{mods.map((pubkey) => (
|
||||
<Flex gap="2">
|
||||
<Flex key={pubkey} gap="2">
|
||||
<UserAvatarLink pubkey={pubkey} size="xs" />
|
||||
<UserLink pubkey={pubkey} />
|
||||
</Flex>
|
||||
@ -99,7 +99,7 @@ export default function VerticalCommunityDetails({
|
||||
</Heading>
|
||||
<Box>
|
||||
{links.map(([url, name]) => (
|
||||
<Link href={url} isTruncated isExternal display="block">
|
||||
<Link key={url + name} href={url} isTruncated isExternal display="block">
|
||||
{name || url}
|
||||
</Link>
|
||||
))}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import FeedStatus from "./feed-status";
|
||||
import { AddressPointer } from "nostr-tools/nip19";
|
||||
import { getEventUID } from "applesauce-core/helpers";
|
||||
|
||||
import { ChainedDVMJob, getEventIdsFromJobs } from "../../../../helpers/nostr/dvm";
|
||||
import useSingleEvents from "../../../../hooks/use-single-events";
|
||||
@ -12,7 +13,7 @@ function FeedEvents({ chain }: { chain: ChainedDVMJob[] }) {
|
||||
return (
|
||||
<>
|
||||
{events.map((event) => (
|
||||
<TimelineItem event={event} visible />
|
||||
<TimelineItem key={getEventUID(event)} event={event} visible />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
|
@ -15,7 +15,7 @@ export default function GoalContents({ goal }: { goal: NostrEvent }) {
|
||||
<EmbedEventPointer key={encodeDecodeResult(pointer)} pointer={pointer} />
|
||||
))}
|
||||
{links.map((link) => (
|
||||
<OpenGraphCard url={new URL(link)} />
|
||||
<OpenGraphCard key={link} url={new URL(link)} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
|
@ -44,7 +44,7 @@ function RenderRedirect({ event, link }: { event?: NostrEvent; link: string }) {
|
||||
return <Navigate to={`/n/${link}`} replace />;
|
||||
case "nevent":
|
||||
case "naddr": {
|
||||
let k = decoded.data.kind || event?.kind;
|
||||
const k = decoded.data.kind || event?.kind;
|
||||
if (k === kinds.ShortTextNote) return <Navigate to={`/n/${link}`} replace />;
|
||||
if (k === TORRENT_KIND) return <Navigate to={`/torrents/${link}`} replace />;
|
||||
if (k === kinds.LiveEvent) return <Navigate to={`/streams/${link}`} replace />;
|
||||
|
@ -85,7 +85,7 @@ function ListPage({ list }: { list: NostrEvent }) {
|
||||
<Heading size="lg">People</Heading>
|
||||
<SimpleGrid columns={{ base: 1, lg: 2, xl: 3 }} spacing="2">
|
||||
{people.map(({ pubkey, relay }) => (
|
||||
<UserCard pubkey={pubkey} relay={relay} list={list} />
|
||||
<UserCard key={pubkey} pubkey={pubkey} relay={relay} list={list} />
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</>
|
||||
@ -96,7 +96,7 @@ function ListPage({ list }: { list: NostrEvent }) {
|
||||
<Heading size="lg">Notes</Heading>
|
||||
<Flex gap="2" direction="column">
|
||||
{notes.map(({ id, relays }) => (
|
||||
<BookmarkedEvent id={id} relays={relays} />
|
||||
<BookmarkedEvent key={id} id={id} relays={relays} />
|
||||
))}
|
||||
</Flex>
|
||||
</>
|
||||
|
@ -23,7 +23,7 @@ function RelaySetCard({ set }: { set: NostrEvent }) {
|
||||
<CardHeader p="4">{name}</CardHeader>
|
||||
<CardBody px="4" pb="4" pt="0" display="flex" flexDirection="row" gap="2" flexWrap="wrap">
|
||||
{relays.map((relay) => (
|
||||
<Text>
|
||||
<Text key={relay}>
|
||||
<RelayFavicon relay={relay} /> {relay}
|
||||
</Text>
|
||||
))}
|
||||
|
@ -82,7 +82,7 @@ function MediaServersPage() {
|
||||
|
||||
const [confirmServer, setConfirmServer] = useState("");
|
||||
const submit = handleSubmit(async (values) => {
|
||||
let url = new URL(values.server.startsWith("http") ? values.server : "https://" + values.server).toString();
|
||||
const url = new URL(values.server.startsWith("http") ? values.server : "https://" + values.server).toString();
|
||||
|
||||
if (event?.tags.some((t) => isServerTag(t) && areServersEqual(t[1], url)))
|
||||
return toast({ status: "error", description: "Server already in list" });
|
||||
|
@ -102,7 +102,7 @@ export default function RelayDetailsTab({ relay }: { relay: string }) {
|
||||
const token = theme.semanticTokens.colors["chakra-body-text"];
|
||||
const color = useColorModeValue(token._light, token._dark) as string;
|
||||
|
||||
const [_, update] = useState<Object>();
|
||||
const [_, update] = useState<object>();
|
||||
const store = useMemo(() => new EventStore(), []);
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
@ -32,7 +32,7 @@ export function SearchPage() {
|
||||
const searchQuery = params.get("q") || "";
|
||||
|
||||
const relayURL = params.get("relay");
|
||||
let searchRelay = useMemo(() => {
|
||||
const searchRelay = useMemo(() => {
|
||||
if (relayURL === "local") return localRelay;
|
||||
else if (relayURL) return relayPoolService.requestRelay(relayURL);
|
||||
else if (localSearchSupported) return localRelay;
|
||||
|
@ -27,7 +27,7 @@ export default function LoginNostrAddressView() {
|
||||
async () => {
|
||||
if (!address) return setNip05(undefined);
|
||||
if (!getMatchSimpleEmail().test(address)) return setNip05(undefined);
|
||||
let [name, domain] = address.split("@");
|
||||
const [name, domain] = address.split("@");
|
||||
if (!name || !domain) return setNip05(undefined);
|
||||
setNip05((await dnsIdentityService.fetchIdentity(address)) ?? null);
|
||||
setRootNip05((await dnsIdentityService.fetchIdentity(`_@${domain}`)) ?? null);
|
||||
|
@ -58,7 +58,7 @@ function ClientConnectForm() {
|
||||
<>
|
||||
{signer ? (
|
||||
<>
|
||||
<a href={connectionURL} target="_blank">
|
||||
<a href={connectionURL} target="_blank" rel="noreferrer">
|
||||
<QrCodeSvg content={connectionURL} />
|
||||
</a>
|
||||
<Flex gap="2">
|
||||
@ -109,7 +109,7 @@ export default function LoginNostrConnectView() {
|
||||
|
||||
try {
|
||||
setLoading("Connecting...");
|
||||
let client = await NostrConnectSigner.fromBunkerURI(connection, relayPoolService, NOSTR_CONNECT_PERMISSIONS);
|
||||
const client = await NostrConnectSigner.fromBunkerURI(connection, relayPoolService, NOSTR_CONNECT_PERMISSIONS);
|
||||
const pubkey = await client.getPublicKey();
|
||||
|
||||
const account = new NostrConnectAccount(pubkey, client);
|
||||
|
@ -4,7 +4,7 @@ import { ComponentWithAs, IconProps } from "@chakra-ui/react";
|
||||
import Process from "../../../../classes/process";
|
||||
|
||||
export default function ProcessIcon({ process, ...props }: { process: Process } & IconProps) {
|
||||
let IconComponent: ComponentWithAs<"svg", IconProps> = process.icon || QuestionIcon;
|
||||
const IconComponent: ComponentWithAs<"svg", IconProps> = process.icon || QuestionIcon;
|
||||
|
||||
return <IconComponent color={process.active ? "green.500" : "gray.500"} {...props} />;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import { Button, Flex, Spinner, Text, Textarea, useToast } from "@chakra-ui/reac
|
||||
import { EventTemplate, NostrEvent } from "nostr-tools";
|
||||
import { MultiSubscription } from "applesauce-net/subscription";
|
||||
import { useStoreQuery } from "applesauce-react/hooks";
|
||||
import { unixNow } from "applesauce-core/helpers";
|
||||
import { getEventUID, unixNow } from "applesauce-core/helpers";
|
||||
|
||||
import { useUserInbox } from "../../../../../hooks/use-user-mailboxes";
|
||||
import useCurrentAccount from "../../../../../hooks/use-current-account";
|
||||
@ -86,7 +86,7 @@ export default function EventSummarizePage({ event }: { event: NostrEvent }) {
|
||||
{responses ? (
|
||||
<>
|
||||
{Object.entries(responses).map(([pubkey, event]) => (
|
||||
<DVMStatusCard status={event} />
|
||||
<DVMStatusCard key={getEventUID(event)} status={event} />
|
||||
))}
|
||||
</>
|
||||
) : submitted ? (
|
||||
|
@ -104,7 +104,7 @@ export default function EventConsoleView() {
|
||||
}
|
||||
|
||||
await new Promise<void>((res) => {
|
||||
let buffer: NostrEvent[] = [];
|
||||
const buffer: NostrEvent[] = [];
|
||||
const flush = _throttle(() => setEvents([...buffer]), 1000 / 10, { trailing: true });
|
||||
|
||||
setError("");
|
||||
|
@ -5,11 +5,11 @@ import { SearchDirectory, userSearchDirectory } from "../../../services/username
|
||||
|
||||
let users: SearchDirectory = [];
|
||||
export function codeMirrorUserAutocomplete(context: CompletionContext): CompletionResult | null {
|
||||
let nodeBefore = syntaxTree(context.state).resolveInner(context.pos, -1);
|
||||
const nodeBefore = syntaxTree(context.state).resolveInner(context.pos, -1);
|
||||
if (nodeBefore.name !== "String") return null;
|
||||
|
||||
let textBefore = context.state.sliceDoc(nodeBefore.from, context.pos);
|
||||
let tagBefore = /@\w*$/.exec(textBefore);
|
||||
const textBefore = context.state.sliceDoc(nodeBefore.from, context.pos);
|
||||
const tagBefore = /@\w*$/.exec(textBefore);
|
||||
if (!tagBefore && !context.explicit) return null;
|
||||
|
||||
return {
|
||||
|
@ -158,7 +158,9 @@ function EventPublisherPage({ initDraft }: { initDraft?: LooseEventTemplate }) {
|
||||
<Text fontWeight="bold">Template</Text>
|
||||
<Select onChange={(e) => selectTemplate(e.target.value)} w="auto">
|
||||
{TEMPLATES.map((template) => (
|
||||
<option value={template.name}>{template.name}</option>
|
||||
<option key={template.name} value={template.name}>
|
||||
{template.name}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
<Spacer />
|
||||
|
@ -72,7 +72,7 @@ export function NoteTranslationsPage({ note }: { note: NostrEvent }) {
|
||||
<Flex gap="2">
|
||||
<Select value={lang} onChange={(e) => setLang(e.target.value)} w="60">
|
||||
{codes.map((code) => (
|
||||
<option value={code.iso639_1}>
|
||||
<option key={code.iso639_1} value={code.iso639_1}>
|
||||
{code.name} ({code.nativeName})
|
||||
</option>
|
||||
))}
|
||||
|
@ -45,7 +45,7 @@ function TorrentTableRow({ torrent }: { torrent: NostrEvent }) {
|
||||
<Td>
|
||||
{categories
|
||||
.map((c) => (
|
||||
<Link as={RouterLink} to={createTagLink(c)}>
|
||||
<Link key={c.name} as={RouterLink} to={createTagLink(c)}>
|
||||
{c.name}
|
||||
</Link>
|
||||
))
|
||||
|
@ -202,7 +202,7 @@ export default function NewTorrentView() {
|
||||
</Flex>
|
||||
<Flex direction="column" gap="2">
|
||||
{getValues().files.map((file, i) => (
|
||||
<Flex gap="2">
|
||||
<Flex gap="2" key={file.name + file.size}>
|
||||
<Input
|
||||
type="text"
|
||||
value={file.name}
|
||||
|
@ -27,7 +27,7 @@ export default function TrackPlayer({ track }: { track: NostrEvent }) {
|
||||
position="relative"
|
||||
>
|
||||
<IconButton aria-label="Play" mr="4" icon={<Play />} onClick={showPlayer.onOpen} size="md" variant="outline" />
|
||||
{waveform?.map((v) => <Box h={v + "%"} w="3px" bg="primary.800" />)}
|
||||
{waveform?.map((v, i) => <Box key={v + i} h={v + "%"} w="3px" bg="primary.800" />)}
|
||||
</Flex>
|
||||
);
|
||||
|
||||
|
@ -11,7 +11,7 @@ export default function UserZapButton({ pubkey, ...props }: { pubkey: string } &
|
||||
if (!metadata) return null;
|
||||
|
||||
// use lud06 and lud16 fields interchangeably
|
||||
let tipAddress = metadata.lud06 || metadata.lud16;
|
||||
const tipAddress = metadata.lud06 || metadata.lud16;
|
||||
|
||||
if (!tipAddress) return null;
|
||||
|
||||
|
@ -2,7 +2,7 @@ import { Box, Card, CardBody, CardHeader, CardProps, Heading, LinkBox, Text } fr
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
|
||||
import { NostrEvent } from "../../../types/nostr-event";
|
||||
import { getVideoDuration, getVideoImages, getVideoSummary, getVideoTitle } from "../../../helpers/nostr/video";
|
||||
import { getVideoImages, getVideoSummary, getVideoTitle } from "../../../helpers/nostr/video";
|
||||
import HoverLinkOverlay from "../../../components/hover-link-overlay";
|
||||
import useEventIntersectionRef from "../../../hooks/use-event-intersection-ref";
|
||||
import useShareableEventAddress from "../../../hooks/use-shareable-event-address";
|
||||
@ -10,14 +10,13 @@ import useShareableEventAddress from "../../../hooks/use-shareable-event-address
|
||||
export default function VideoCard({ video, ...props }: Omit<CardProps, "children"> & { video: NostrEvent }) {
|
||||
const title = getVideoTitle(video);
|
||||
const { thumb } = getVideoImages(video);
|
||||
const duration = getVideoDuration(video);
|
||||
const summary = getVideoSummary(video);
|
||||
|
||||
const ref = useEventIntersectionRef(video);
|
||||
const address = useShareableEventAddress(video);
|
||||
|
||||
return (
|
||||
<Card as={LinkBox} {...props}>
|
||||
<Card as={LinkBox} ref={ref} {...props}>
|
||||
<Box
|
||||
backgroundImage={thumb}
|
||||
aspectRatio={16 / 9}
|
||||
|
Loading…
x
Reference in New Issue
Block a user