diff --git a/package.json b/package.json
index 71dd50c..d757bba 100644
--- a/package.json
+++ b/package.json
@@ -8,11 +8,11 @@
"@noble/hashes": "^1.4.0",
"@scure/base": "^1.1.6",
"@snort/shared": "^1.0.17",
- "@snort/system": "^1.5.6",
- "@snort/system-react": "^1.5.6",
+ "@snort/system": "^1.6.1",
+ "@snort/system-react": "^1.6.1",
"@snort/system-wasm": "^1.0.5",
- "@snort/wallet": "^0.2.1",
- "@snort/worker-relay": "^1.3.0",
+ "@snort/wallet": "^0.2.4",
+ "@snort/worker-relay": "^1.3.1",
"@szhsin/react-menu": "^4.1.0",
"@types/webscopeio__react-textarea-autocomplete": "^4.7.5",
"@webscopeio/react-textarea-autocomplete": "^4.9.2",
diff --git a/src/const.ts b/src/const.ts
index 02c0f13..57c1818 100644
--- a/src/const.ts
+++ b/src/const.ts
@@ -8,8 +8,10 @@ export const GOAL = 9041 as EventKind;
export const USER_CARDS = 17_777 as EventKind;
export const CARD = 37_777 as EventKind;
-export const VIDEO_KIND = 34_235 as EventKind;
-export const SHORTS_KIND = 34_236 as EventKind;
+export const VIDEO_KIND = 21 as EventKind;
+export const SHORTS_KIND = 22 as EventKind;
+export const OLD_VIDEO_KIND = 34_235 as EventKind;
+export const OLD_SHORTS_KIND = 34_236 as EventKind;
export const MINUTE = 60;
export const HOUR = 60 * MINUTE;
diff --git a/src/element/event-embed.tsx b/src/element/event-embed.tsx
index 11bfa00..a50c0ce 100644
--- a/src/element/event-embed.tsx
+++ b/src/element/event-embed.tsx
@@ -5,13 +5,15 @@ import { Goal } from "./goal";
import { Note } from "./note";
import { EmojiPack } from "./emoji-pack";
import { BadgeInfo } from "./badge";
-import { GOAL, LIVE_STREAM_CLIP, StreamState } from "@/const";
+import { GOAL, LIVE_STREAM_CLIP, OLD_SHORTS_KIND, OLD_VIDEO_KIND, SHORTS_KIND, StreamState, VIDEO_KIND } from "@/const";
import { useEventFeed } from "@snort/system-react";
import LiveStreamClip from "./stream/clip";
import { ExternalLink } from "./external-link";
import { extractStreamInfo } from "@/utils";
import LiveVideoPlayer from "./stream/live-video-player";
-import { HTMLProps } from "react";
+import { HTMLProps, ReactNode } from "react";
+import { ShortPage } from "@/pages/short";
+import { VideoPage } from "@/pages/video";
interface EventProps {
link: NostrLink;
@@ -31,36 +33,49 @@ export function EventIcon({ kind }: { kind?: EventKind }) {
}
export function NostrEvent({ ev }: { ev: TaggedNostrEvent }) {
+ const link = NostrLink.fromEvent(ev);
+ function modalPage(inner: ReactNode) {
+ return
{inner}
;
+ }
+
switch (ev.kind) {
case GOAL: {
- return ;
+ return modalPage();
}
case EventKind.EmojiSet: {
- return ;
+ return modalPage();
}
case EventKind.Badge: {
- return ;
+ return modalPage();
}
case EventKind.TextNote: {
- return ;
+ return modalPage();
}
case LIVE_STREAM_CLIP: {
- return ;
+ return modalPage();
+ }
+ case OLD_SHORTS_KIND:
+ case SHORTS_KIND: {
+ return ;
+ }
+ case OLD_VIDEO_KIND:
+ case VIDEO_KIND: {
+ return ;
}
case EventKind.LiveEvent: {
const info = extractStreamInfo(ev);
- return (
+ return modalPage(
+ />,
);
}
default: {
- const link = NostrLink.fromEvent(ev);
- return {link.encode()};
+ return modalPage({link.encode()});
}
}
}
diff --git a/src/element/stream-editor/index.tsx b/src/element/stream-editor/index.tsx
index 6be5802..a49e31c 100644
--- a/src/element/stream-editor/index.tsx
+++ b/src/element/stream-editor/index.tsx
@@ -145,7 +145,7 @@ export function StreamEditor({ ev, onFinish, options }: StreamEditorProps) {
}
}
- const startsTimestamp = parseInt(start ?? (new Date() / 1000));
+ const startsTimestamp = Number(start ?? (new Date().getTime() / 1000));
const startsDate = new Date(startsTimestamp * 1000);
return (
diff --git a/src/hooks/current-stream-feed.ts b/src/hooks/current-stream-feed.ts
index bf9fdc0..d0c814f 100644
--- a/src/hooks/current-stream-feed.ts
+++ b/src/hooks/current-stream-feed.ts
@@ -1,13 +1,10 @@
-import { unwrap } from "@snort/shared";
import { NostrLink, NostrPrefix, RequestBuilder, TaggedNostrEvent } from "@snort/system";
import { useRequestBuilder } from "@snort/system-react";
import { useMemo } from "react";
import { LIVE_STREAM } from "@/const";
-import { getHost } from "@/utils";
export function useCurrentStreamFeed(link: NostrLink, leaveOpen = false, evPreload?: TaggedNostrEvent) {
- const author = link.type === NostrPrefix.Address ? unwrap(link.author) : link.id;
const sub = useMemo(() => {
const b = new RequestBuilder(`current-event:${link.id}`);
b.withOptions({
@@ -16,14 +13,8 @@ export function useCurrentStreamFeed(link: NostrLink, leaveOpen = false, evPrelo
if (link.type === NostrPrefix.PublicKey || link.type === NostrPrefix.Profile) {
b.withFilter().authors([link.id]).kinds([LIVE_STREAM]);
b.withFilter().tag("p", [link.id]).kinds([LIVE_STREAM]);
- } else if (link.type === NostrPrefix.Address) {
- const f = b.withFilter().tag("d", [link.id]);
- if (link.author) {
- f.authors([link.author]);
- }
- if (link.kind) {
- f.kinds([link.kind]);
- }
+ } else {
+ b.withFilter().link(link);
}
return b;
}, [link.id, leaveOpen]);
@@ -31,9 +22,7 @@ export function useCurrentStreamFeed(link: NostrLink, leaveOpen = false, evPrelo
const q = useRequestBuilder(sub);
return useMemo(() => {
- const hosting = [...q, ...(evPreload ? [evPreload] : [])]
- .filter(a => getHost(a) === author || a.pubkey === author)
- .sort((a, b) => (b.created_at > a.created_at ? 1 : -1));
+ const hosting = [...q, ...(evPreload ? [evPreload] : [])].sort((a, b) => (b.created_at > a.created_at ? 1 : -1));
return hosting.at(0);
}, [q]);
}
diff --git a/src/hooks/dead-link.ts b/src/hooks/dead-link.ts
index c277e0b..0c5256d 100644
--- a/src/hooks/dead-link.ts
+++ b/src/hooks/dead-link.ts
@@ -1,4 +1,4 @@
-import { SHORTS_KIND, VIDEO_KIND } from "@/const";
+import { OLD_SHORTS_KIND, OLD_VIDEO_KIND, SHORTS_KIND, VIDEO_KIND } from "@/const";
import { MediaPayload, VideoInfo } from "@/service/video/info";
import { findTag } from "@/utils";
import { NostrEvent, TaggedNostrEvent } from "@snort/system";
@@ -58,7 +58,7 @@ export function useDeadLink(ev: TaggedNostrEvent | NostrEvent) {
useEffect(() => {
const links =
- ev.kind === VIDEO_KIND || ev.kind === SHORTS_KIND
+ ev.kind === VIDEO_KIND || ev.kind === SHORTS_KIND || ev.kind == OLD_SHORTS_KIND || ev.kind == OLD_VIDEO_KIND
? VideoInfo.parse(ev)?.sources()
: [
{
diff --git a/src/hooks/media-servers.ts b/src/hooks/media-servers.ts
index a92ee2b..8ceb012 100644
--- a/src/hooks/media-servers.ts
+++ b/src/hooks/media-servers.ts
@@ -4,12 +4,7 @@ import { removeUndefined, sanitizeRelayUrl } from "@snort/shared";
import { Nip96Server } from "@/service/upload/nip96";
import { useMemo } from "react";
-export const DefaultMediaServers = [
- //"https://media.zap.stream",
- new UnknownTag(["server", "https://nostr.build/"]),
- new UnknownTag(["server", "https://nostrcheck.me/"]),
- new UnknownTag(["server", "https://files.v0l.io/"]),
-];
+export const DefaultMediaServers = [new UnknownTag(["server", "https://nostr.download/"])];
export function useMediaServerList() {
const login = useLogin();
diff --git a/src/lang.json b/src/lang.json
index 77d6dba..97bd95d 100644
--- a/src/lang.json
+++ b/src/lang.json
@@ -221,6 +221,9 @@
"BD0vyn": {
"defaultMessage": "{name} created a clip"
},
+ "BHNL+v": {
+ "defaultMessage": "Raw Data:"
+ },
"Bd1yEX": {
"defaultMessage": "New Stream Goal"
},
@@ -641,6 +644,9 @@
"ZcgtZo": {
"defaultMessage": "We've put together a list of easy-to-use exchanges that will allow you to buy a small amount of bitcoin (sats) and to transfer them to your wallet of choice."
},
+ "Zfr//4": {
+ "defaultMessage": "No duration provided, please try another upload server."
+ },
"ZmqxZs": {
"defaultMessage": "You can change this later"
},
@@ -705,6 +711,9 @@
"dkUMIH": {
"defaultMessage": "Clip by {name}"
},
+ "dqGkI+": {
+ "defaultMessage": "Video durations vary too much, are you sure each variant is the same video?"
+ },
"e011kf": {
"defaultMessage": "FAQ",
"description": "Title: FAQ page"
@@ -945,6 +954,9 @@
"vP4dFa": {
"defaultMessage": "Visit {link} to get some sweet zap.stream merch!"
},
+ "vaZKTn": {
+ "defaultMessage": "Add more content"
+ },
"vrTOHJ": {
"defaultMessage": "{amount} sats"
},
diff --git a/src/pages/link-handler.tsx b/src/pages/link-handler.tsx
index 1e15ff8..a154891 100644
--- a/src/pages/link-handler.tsx
+++ b/src/pages/link-handler.tsx
@@ -1,4 +1,4 @@
-import { LIVE_STREAM, SHORTS_KIND, VIDEO_KIND } from "@/const";
+import { LIVE_STREAM, OLD_SHORTS_KIND, OLD_VIDEO_KIND, SHORTS_KIND, VIDEO_KIND } from "@/const";
import { useStreamLink } from "@/hooks/stream-link";
import { getEventFromLocationState } from "@/utils";
import { NostrPrefix } from "@snort/system";
@@ -20,20 +20,16 @@ export function LinkHandler() {
if (!link) return;
if (link.type === NostrPrefix.Event) {
- return (
-
-
-
- );
+ return ;
} else if (link.kind === LIVE_STREAM || link.type === NostrPrefix.PublicKey) {
return (
);
- } else if (link.kind === VIDEO_KIND) {
+ } else if (link.kind === VIDEO_KIND || link.kind === OLD_VIDEO_KIND) {
return ;
- } else if (link.kind === SHORTS_KIND) {
+ } else if (link.kind === SHORTS_KIND || link.kind === OLD_SHORTS_KIND) {
return ;
} else {
return (
diff --git a/src/pages/shorts.tsx b/src/pages/shorts.tsx
index 75739f8..3f3cee5 100644
--- a/src/pages/shorts.tsx
+++ b/src/pages/shorts.tsx
@@ -1,4 +1,4 @@
-import { SHORTS_KIND } from "@/const";
+import { OLD_SHORTS_KIND, SHORTS_KIND } from "@/const";
import VideoGrid from "@/element/video-grid";
import { VideoTile } from "@/element/video/video-tile";
import { findTag } from "@/utils";
@@ -8,13 +8,12 @@ import { FormattedMessage } from "react-intl";
export function ShortsPage() {
const rb = new RequestBuilder("shorts");
- rb.withFilter().kinds([SHORTS_KIND]);
+ rb.withFilter().kinds([SHORTS_KIND, OLD_SHORTS_KIND]);
const videos = useRequestBuilder(rb);
-
const sorted = videos.sort((a, b) => {
- const pubA = findTag(a, "published_at");
- const pubB = findTag(b, "published_at");
+ const pubA = findTag(a, "published_at") ?? a.created_at;
+ const pubB = findTag(b, "published_at") ?? b.created_at;
return Number(pubA) > Number(pubB) ? -1 : 1;
});
diff --git a/src/pages/upload.tsx b/src/pages/upload.tsx
index a87ba87..fbef92e 100644
--- a/src/pages/upload.tsx
+++ b/src/pages/upload.tsx
@@ -1,4 +1,4 @@
-import { VIDEO_KIND } from "@/const";
+import { SHORTS_KIND, VIDEO_KIND } from "@/const";
import { DefaultButton, IconButton, Layer3Button, PrimaryButton, WarningButton } from "@/element/buttons";
import { Icon } from "@/element/icon";
import Modal from "@/element/modal";
@@ -9,11 +9,11 @@ import { ServerList } from "@/element/upload/server-list";
import useImgProxy from "@/hooks/img-proxy";
import { useLogin } from "@/hooks/login";
import { useMediaServerList } from "@/hooks/media-servers";
-import { Nip94Tags, UploadResult, nip94TagsToIMeta } from "@/service/upload";
+import { Nip94Tags, UploadResult, nip94TagsToIMeta, readNip94Tags } from "@/service/upload";
import { Nip96Server } from "@/service/upload/nip96";
import { openFile } from "@/utils";
-import { ExternalStore, removeUndefined, unixNow, unwrap } from "@snort/shared";
-import { EventPublisher, NostrLink } from "@snort/system";
+import { ExternalStore, removeUndefined, unwrap } from "@snort/shared";
+import { EventBuilder, EventPublisher, NostrEvent, NostrLink } from "@snort/system";
import { SnortContext } from "@snort/system-react";
import { useContext, useEffect, useState, useSyncExternalStore } from "react";
import { FormattedMessage, useIntl } from "react-intl";
@@ -69,6 +69,23 @@ class UploadManager extends ExternalStore> {
}
}
+ addUpload(server: string, file: NostrEvent, meta: Nip94Tags, type: UploadStatus["type"]) {
+ const name = file.content ?? meta.summary ?? meta.alt ?? "";
+ const uploadKey = `${name}:${server}:${type}`;
+ this.#uploads.set(uploadKey, {
+ type,
+ name,
+ size: meta.size ?? 0,
+ server,
+ result: {
+ url: meta.url,
+ header: file,
+ metadata: meta,
+ },
+ });
+ this.notifyChange();
+ }
+
async uploadTo(server: string, file: File, pub: EventPublisher, type: UploadStatus["type"]) {
let uploader = this.#uploaders.get(server);
if (!uploader) {
@@ -130,6 +147,27 @@ class UploadManager extends ExternalStore> {
return resGroup;
}
+ /**
+ * Gets the [min, max] duration from all variants
+ */
+ duration() {
+ const uploads = this.snapshot();
+ return uploads.reduce(
+ (acc, v) => {
+ if (v.result?.metadata?.duration) {
+ if (acc[1] < v.result.metadata.duration) {
+ acc[1] = v.result.metadata.duration;
+ }
+ if (acc[0] > v.result.metadata.duration) {
+ acc[0] = v.result.metadata.duration;
+ }
+ }
+ return acc;
+ },
+ [1_000_000, 0],
+ );
+ }
+
/**
* Create the `imeta` tag for this upload
*/
@@ -187,21 +225,24 @@ export function UploadPage() {
return error.length == 0 && uploads.length > 0 && uploads.every(a => a.result !== undefined);
}
+ function makeEvent() {
+ const duration = manager.duration();
+ const eb = new EventBuilder()
+ .pubKey(login?.pubkey ?? "00".repeat(31))
+ .kind(duration[1] <= 60 ? SHORTS_KIND : VIDEO_KIND)
+ .tag(["title", title])
+ .content(summary);
+
+ const imeta = manager.makeIMeta();
+ imeta.forEach(a => eb.tag(a));
+
+ return eb;
+ }
+
async function publish() {
const pub = login?.publisher();
if (!pub) return;
- const ev = await pub.generic(eb => {
- eb.kind(VIDEO_KIND);
- eb.tag(["d", manager.id]);
- eb.tag(["title", title]);
- eb.tag(["published_at", unixNow().toString()]);
- eb.content(summary);
-
- const imeta = manager.makeIMeta();
- imeta.forEach(a => eb.tag(a));
-
- return eb;
- });
+ const ev = await makeEvent().buildAndSign(pub.signer);
console.debug(ev);
await system.BroadcastEvent(ev);
navigate(`/${NostrLink.fromEvent(ev).encode()}`);
@@ -229,7 +270,16 @@ export function UploadPage() {
const data = await rsp.blob();
const pub = login?.publisher();
if (pub) {
- servers.servers.forEach(b => manager.uploadTo(b, new File([data], "thumb.jpg"), pub, "thumb"));
+ servers.servers.forEach(b =>
+ manager.uploadTo(
+ b,
+ new File([data], "thumb.jpg", {
+ type: "image/jpeg",
+ }),
+ pub,
+ "thumb",
+ ),
+ );
}
}
}
@@ -291,6 +341,17 @@ export function UploadPage() {
}),
);
}
+ const d = manager.duration();
+ if (d[0] === 0 || d[1] === 0) {
+ err.push(formatMessage({ defaultMessage: "No duration provided, please try another upload server." }));
+ }
+ if (Math.abs(d[0] - d[1]) >= 0.5) {
+ err.push(
+ formatMessage({
+ defaultMessage: "Video durations vary too much, are you sure each variant is the same video?",
+ }),
+ );
+ }
setError(err);
}
@@ -312,6 +373,7 @@ export function UploadPage() {
>
);
};
+
return (
@@ -359,8 +421,11 @@ export function UploadPage() {
))}
{videos > 0 && (
-
uploadFile()} className="cursor-pointer">
- {uploadButton()}
+
)}
{uploads.length > 0 && (
@@ -377,7 +442,7 @@ export function UploadPage() {
- {thumb &&
![]({proxy(thumb)})
}
+ {thumb &&
![]({proxy(thumb)})
}
uploadThumb()}>
@@ -405,9 +470,13 @@ export function UploadPage() {
-
- {JSON.stringify(manager.makeIMeta(), undefined, 2)}
-
+
+
+
+
+ {JSON.stringify(makeEvent().build(), undefined, 2)}
+
+
{editServers && (
setEditServers(false)}>
@@ -416,7 +485,19 @@ export function UploadPage() {
{mediaPicker && (
setMediaPicker(false)} largeModal={true}>
{
+ onPicked={files => {
+ files.forEach(f => {
+ const meta = readNip94Tags(f.tags);
+ if (meta.url) {
+ const url = new URL(meta.url);
+ manager.addUpload(
+ `${url.protocol}//${url.host}/`,
+ f,
+ meta,
+ meta.mimeType?.startsWith("image/") ?? false ? "thumb" : "video",
+ );
+ }
+ });
setMediaPicker(false);
}}
/>
diff --git a/src/pages/videos.tsx b/src/pages/videos.tsx
index 86c7f3b..37f6cd2 100644
--- a/src/pages/videos.tsx
+++ b/src/pages/videos.tsx
@@ -1,4 +1,4 @@
-import { VIDEO_KIND } from "@/const";
+import { OLD_VIDEO_KIND, VIDEO_KIND } from "@/const";
import VideoGrid from "@/element/video-grid";
import { findTag, getHost } from "@/utils";
import { NostrLink, RequestBuilder } from "@snort/system";
@@ -11,7 +11,7 @@ export function VideosPage() {
const login = useLogin();
const rb = new RequestBuilder("videos");
- rb.withFilter().kinds([VIDEO_KIND]);
+ rb.withFilter().kinds([VIDEO_KIND, OLD_VIDEO_KIND]);
const videos = useRequestBuilder(rb);
@@ -22,8 +22,8 @@ export function VideosPage() {
return (login?.state?.muted.length ?? 0) === 0 || !login?.state?.muted.some(a => a.equals(link));
})
.sort((a, b) => {
- const pubA = findTag(a, "published_at");
- const pubB = findTag(b, "published_at");
+ const pubA = findTag(a, "published_at") ?? a.created_at;
+ const pubB = findTag(b, "published_at") ?? b.created_at;
return Number(pubA) > Number(pubB) ? -1 : 1;
});
diff --git a/src/service/upload/index.ts b/src/service/upload/index.ts
index b664c56..878b29b 100644
--- a/src/service/upload/index.ts
+++ b/src/service/upload/index.ts
@@ -16,6 +16,8 @@ export interface Nip94Tags {
summary?: string;
alt?: string;
fallback?: Array;
+ duration?: number;
+ bitrate?: number;
}
export interface UploadResult {
@@ -103,6 +105,14 @@ export function readNip94Tags(tags: Array>) {
res.fallback.push(v);
break;
}
+ case "duration": {
+ res.duration = Number(v);
+ break;
+ }
+ case "bitrate": {
+ res.bitrate = Number(v);
+ break;
+ }
}
}
return res;
@@ -126,6 +136,8 @@ export function nip94TagsToIMeta(meta: Nip94Tags) {
ifPush("thumb", meta.thumb);
ifPush("summary", meta.summary);
ifPush("alt", meta.alt);
+ ifPush("duration", meta.duration);
+ ifPush("bitrate", meta.bitrate);
if (meta.image) {
meta.image.forEach(a => ifPush("image", a));
}
diff --git a/src/service/upload/nip96.ts b/src/service/upload/nip96.ts
index 60c8ca4..847e9dc 100644
--- a/src/service/upload/nip96.ts
+++ b/src/service/upload/nip96.ts
@@ -37,7 +37,7 @@ export class Nip96Server {
const fd = new FormData();
fd.append("size", file.size.toString());
fd.append("caption", filename);
- fd.append("media_type", file.type);
+ fd.append("content_type", file.type);
fd.append("file", file);
const rsp = await this.#req("", "POST", fd);
diff --git a/src/service/video/info.ts b/src/service/video/info.ts
index ede07f3..cfb0d14 100644
--- a/src/service/video/info.ts
+++ b/src/service/video/info.ts
@@ -2,7 +2,6 @@ import { NostrEvent } from "@snort/system";
import { GameInfo } from "../game-database";
import { Nip94Tags, readNip94Tags, readNip94TagsFromIMeta } from "../upload";
import { getHost, sortStreamTags, extractGameTag, findTag } from "@/utils";
-import { unwrap } from "@snort/shared";
export interface MediaPayload {
url: string;
@@ -19,9 +18,12 @@ export class VideoInfo {
goal?: string;
gameId?: string;
gameInfo?: GameInfo;
- duration?: number;
publishedAt?: number;
+ get duration() {
+ return this.media.find(m => m.duration)?.duration;
+ }
+
constructor(
readonly host: string,
readonly id: string,
@@ -31,28 +33,13 @@ export class VideoInfo {
static parse(ev: NostrEvent) {
const { regularTags, prefixedTags } = sortStreamTags(ev.tags);
- const ret = new VideoInfo(getHost(ev), unwrap(findTag(ev, "d")), regularTags, VideoInfo.#parseMediaTags(ev.tags));
+ const ret = new VideoInfo(getHost(ev), findTag(ev, "d") ?? ev.id, regularTags, VideoInfo.#parseMediaTags(ev.tags));
- const matchInto = (
- tag: Array,
- key: string,
- into: K,
- fn?: (v: string) => never,
- ) => {
- if (tag[0] === key) {
- ret[into] = fn ? fn(tag[1]) : (tag[1] as never);
- }
- };
-
- for (const t of ev.tags) {
- matchInto(t, "d", "id");
- matchInto(t, "title", "title");
- matchInto(t, "summary", "summary");
- matchInto(t, "content-warning", "contentWarning");
- matchInto(t, "goal", "goal");
- matchInto(t, "duration", "duration");
- matchInto(t, "published_at", "publishedAt");
- }
+ ret.title = findTag(ev, "title");
+ ret.summary = findTag(ev, "summary") ?? ev.content;
+ ret.contentWarning = findTag(ev, "content-warning");
+ ret.goal = findTag(ev, "goal");
+ ret.publishedAt = Number(findTag(ev, "published_at") ?? ev.created_at);
const { gameInfo, gameId } = extractGameTag(prefixedTags);
ret.gameId = gameId;
diff --git a/src/translations/en.json b/src/translations/en.json
index 0434cfd..23165a4 100644
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -73,6 +73,7 @@
"Axo/o5": "Science & Technology",
"AyGauy": "Login",
"BD0vyn": "{name} created a clip",
+ "BHNL+v": "Raw Data:",
"Bd1yEX": "New Stream Goal",
"Bep/gA": "Private key",
"BzQPM+": "Destination",
@@ -211,6 +212,7 @@
"ZXp0z1": "Features",
"ZaNcK4": "No goals yet",
"ZcgtZo": "We've put together a list of easy-to-use exchanges that will allow you to buy a small amount of bitcoin (sats) and to transfer them to your wallet of choice.",
+ "Zfr//4": "No duration provided, please try another upload server.",
"ZmqxZs": "You can change this later",
"ZsYhvh": "Zaps are lightning payments, which are published on nostr as receipts.",
"Zse7yG": "Raid target",
@@ -232,6 +234,7 @@
"dOQCL8": "Display name",
"dVD/AR": "Top Zappers",
"dkUMIH": "Clip by {name}",
+ "dqGkI+": "Video durations vary too much, are you sure each variant is the same video?",
"e011kf": "FAQ",
"ebmhes": "Nostr Extension",
"f6biFA": "Oh, and you have {n} sats of free streaming on us! 💜",
@@ -311,6 +314,7 @@
"ug01Mk": "Time",
"uksRSi": "Latest Videos",
"vP4dFa": "Visit {link} to get some sweet zap.stream merch!",
+ "vaZKTn": "Add more content",
"vrTOHJ": "{amount} sats",
"w+2Vw7": "Shorts",
"w0Xm2F": "Start typing",
diff --git a/yarn.lock b/yarn.lock
index 5a0b2ca..a5d47be 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2573,14 +2573,14 @@ __metadata:
languageName: node
linkType: hard
-"@snort/system-react@npm:^1.5.6":
- version: 1.5.6
- resolution: "@snort/system-react@npm:1.5.6"
+"@snort/system-react@npm:^1.6.1":
+ version: 1.6.1
+ resolution: "@snort/system-react@npm:1.6.1"
dependencies:
"@snort/shared": "npm:^1.0.17"
- "@snort/system": "npm:^1.5.6"
+ "@snort/system": "npm:^1.6.1"
react: "npm:^18.2.0"
- checksum: 10c0/b7fb8dbc87328603b202dad9ce57dbff2cb8231829128b48346ba10925ee9fa5103652941b6a0456d6221fce8379a7148dc6507ebe8e1d0d35f7efd92738d08a
+ checksum: 10c0/fe3180c1f4341df4fd585c4031ef632a7d59c7637c6aed16ea254a1c22a66e288516d96939c0080efd0fb73940531855a59a24fae5f82c326f6544362eb0394c
languageName: node
linkType: hard
@@ -2591,9 +2591,9 @@ __metadata:
languageName: node
linkType: hard
-"@snort/system@npm:^1.5.6":
- version: 1.5.6
- resolution: "@snort/system@npm:1.5.6"
+"@snort/system@npm:^1.6.1":
+ version: 1.6.1
+ resolution: "@snort/system@npm:1.6.1"
dependencies:
"@noble/ciphers": "npm:^0.6.0"
"@noble/curves": "npm:^1.4.0"
@@ -2608,33 +2608,33 @@ __metadata:
nostr-social-graph: "npm:^1.0.3"
uuid: "npm:^9.0.0"
ws: "npm:^8.14.0"
- checksum: 10c0/38fee2d55240f91a5e6ea0684a4bd94e6f4c56fab9b6a20d9ebef26dcdd17ed6c9a42bf1804c7bcf135a89c6882659baecede6d885dcead4a167d5e3337c9764
+ checksum: 10c0/5da01450970f4a51df98369c4cdd2b8886add3480e7962d11ed17498cf7db421bcd5e585abe532ff754efc0bf26b5734b9b24005f958802357ec390ccb74d281
languageName: node
linkType: hard
-"@snort/wallet@npm:^0.2.1":
- version: 0.2.1
- resolution: "@snort/wallet@npm:0.2.1"
+"@snort/wallet@npm:^0.2.4":
+ version: 0.2.4
+ resolution: "@snort/wallet@npm:0.2.4"
dependencies:
"@cashu/cashu-ts": "npm:^1.0.0-rc.3"
"@lightninglabs/lnc-web": "npm:^0.3.1-alpha"
"@scure/base": "npm:^1.1.6"
"@snort/shared": "npm:^1.0.17"
- "@snort/system": "npm:^1.5.6"
+ "@snort/system": "npm:^1.6.1"
debug: "npm:^4.3.4"
eventemitter3: "npm:^5.0.1"
- checksum: 10c0/0dcf4b0336029e336bd6abcd7b79cf60d6fed08b2ab2847a8e791bb2399646e86c95aefc4dcfea08365c3dea417c362cdfa93939d7c36f037762de601936b331
+ checksum: 10c0/7d3e23d1d79595ee99e041b816cec5e7bfc6f34bfce6f0864a556de82cfcf29200f6978744b0717b5f6873c5c498e2dd9005571171f1f533f235cfbadf205a44
languageName: node
linkType: hard
-"@snort/worker-relay@npm:^1.3.0":
- version: 1.3.0
- resolution: "@snort/worker-relay@npm:1.3.0"
+"@snort/worker-relay@npm:^1.3.1":
+ version: 1.3.1
+ resolution: "@snort/worker-relay@npm:1.3.1"
dependencies:
"@sqlite.org/sqlite-wasm": "npm:^3.46.1-build3"
eventemitter3: "npm:^5.0.1"
uuid: "npm:^9.0.1"
- checksum: 10c0/1a0eb175f50787bbcaa585641bf710347b59f3d3426cbf0f83182a5574bf7a63beb3e5d66bb41506e2d50c3ee904d55670c85c7f1542018936dd5a4ce06726e8
+ checksum: 10c0/19b89e4f96df425d2d73e87fda1f82844bf7f3a1ba114073d0bf4052c9d5fe3eac9e6ca6d88ad8e36b65bae6dfcf69db5cb47828ef1c195419a94bd87ae2ff53
languageName: node
linkType: hard
@@ -7354,11 +7354,11 @@ __metadata:
"@noble/hashes": "npm:^1.4.0"
"@scure/base": "npm:^1.1.6"
"@snort/shared": "npm:^1.0.17"
- "@snort/system": "npm:^1.5.6"
- "@snort/system-react": "npm:^1.5.6"
+ "@snort/system": "npm:^1.6.1"
+ "@snort/system-react": "npm:^1.6.1"
"@snort/system-wasm": "npm:^1.0.5"
- "@snort/wallet": "npm:^0.2.1"
- "@snort/worker-relay": "npm:^1.3.0"
+ "@snort/wallet": "npm:^0.2.4"
+ "@snort/worker-relay": "npm:^1.3.1"
"@szhsin/react-menu": "npm:^4.1.0"
"@testing-library/dom": "npm:^9.3.1"
"@types/node": "npm:^20.12.12"