feat: upload stage
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Kieran 2023-10-16 17:09:05 +01:00
parent dec2b9ce2e
commit f24d9982f4
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
7 changed files with 44 additions and 11 deletions

View File

@ -7,7 +7,7 @@ export default function FileUploadProgress({ progress }: { progress: Array<Uploa
{progress.map(p => ( {progress.map(p => (
<div className="flex-column g2" id={p.id}> <div className="flex-column g2" id={p.id}>
{p.file.name} {p.file.name}
<Progress value={p.progress} /> <Progress value={p.progress} status={p.stage} />
</div> </div>
))} ))}
</div> </div>

View File

@ -1,6 +1,7 @@
import "./NoteCreator.css"; import "./NoteCreator.css";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import { EventKind, NostrPrefix, TaggedNostrEvent, EventBuilder, tryParseNostrLink, NostrLink } from "@snort/system"; import { EventKind, NostrPrefix, TaggedNostrEvent, EventBuilder, tryParseNostrLink, NostrLink } from "@snort/system";
import classNames from "classnames";
import Icon from "Icons/Icon"; import Icon from "Icons/Icon";
import useEventPublisher from "Hooks/useEventPublisher"; import useEventPublisher from "Hooks/useEventPublisher";
@ -454,7 +455,7 @@ export function NoteCreator() {
iconName="pie-chart" iconName="pie-chart"
iconSize={24} iconSize={24}
onClick={() => note.update(v => (v.pollOptions = ["A", "B"]))} onClick={() => note.update(v => (v.pollOptions = ["A", "B"]))}
className="note-creator-icon" className={classNames("note-creator-icon", { active: note.pollOptions !== undefined })}
/> />
)} )}
<AsyncIcon iconName="image-plus" iconSize={24} onClick={attachFile} className="note-creator-icon" /> <AsyncIcon iconName="image-plus" iconSize={24} onClick={attachFile} className="note-creator-icon" />
@ -462,8 +463,9 @@ export function NoteCreator() {
iconName="settings-04" iconName="settings-04"
iconSize={24} iconSize={24}
onClick={() => note.update(v => (v.advanced = !v.advanced))} onClick={() => note.update(v => (v.advanced = !v.advanced))}
className="note-creator-icon" className={classNames("note-creator-icon", { active: note.advanced })}
/> />
<FormattedMessage defaultMessage="Preview" />
</div> </div>
<div className="flex g8"> <div className="flex g8">
<button className="secondary" onClick={cancel}> <button className="secondary" onClick={cancel}>

View File

@ -1,8 +1,8 @@
import { FormattedNumber } from "react-intl";
import "./Progress.css"; import "./Progress.css";
import { CSSProperties } from "react"; import { FormattedNumber } from "react-intl";
import { CSSProperties, ReactNode } from "react";
export default function Progress({ value }: { value: number }) { export default function Progress({ value, status }: { value: number; status?: ReactNode }) {
const v = Math.max(0.01, Math.min(1, value)); const v = Math.max(0.01, Math.min(1, value));
return ( return (
<div className="progress"> <div className="progress">
@ -13,6 +13,7 @@ export default function Progress({ value }: { value: number }) {
} as CSSProperties } as CSSProperties
}></div> }></div>
<span> <span>
{status}
<FormattedNumber value={v} style="percent" /> <FormattedNumber value={v} style="percent" />
</span> </span>
</div> </div>

View File

@ -1,5 +1,5 @@
import { EventKind, EventPublisher } from "@snort/system"; import { EventKind, EventPublisher } from "@snort/system";
import { VoidApi } from "@void-cat/api"; import { UploadState, VoidApi } from "@void-cat/api";
import { FileExtensionRegex, VoidCatHost } from "Const"; import { FileExtensionRegex, VoidCatHost } from "Const";
import { UploadResult } from "Upload"; import { UploadResult } from "Upload";
@ -14,6 +14,7 @@ export default async function VoidCatUpload(
filename: string, filename: string,
publisher?: EventPublisher, publisher?: EventPublisher,
progress?: (n: number) => void, progress?: (n: number) => void,
stage?: (n: "starting" | "hashing" | "uploading" | "done" | undefined) => void,
): Promise<UploadResult> { ): Promise<UploadResult> {
const auth = publisher const auth = publisher
? async (url: string, method: string) => { ? async (url: string, method: string) => {
@ -24,9 +25,28 @@ export default async function VoidCatUpload(
} }
: undefined; : undefined;
const api = new VoidApi(VoidCatHost, auth); const api = new VoidApi(VoidCatHost, auth);
const uploader = api.getUploader(file, undefined, px => { const uploader = api.getUploader(
progress?.(px / file.size); file,
}); sx => {
stage?.(
(() => {
switch (sx) {
case UploadState.Starting:
return "starting";
case UploadState.Hashing:
return "hashing";
case UploadState.Uploading:
return "uploading";
case UploadState.Done:
return "done";
}
})(),
);
},
px => {
progress?.(px / file.size);
},
);
const rsp = await uploader.upload({ const rsp = await uploader.upload({
"V-Strip-Metadata": "true", "V-Strip-Metadata": "true",

View File

@ -56,12 +56,16 @@ export interface UploadProgress {
id: string; id: string;
file: File | Blob; file: File | Blob;
progress: number; progress: number;
stage: UploadStage;
} }
export type UploadStage = "starting" | "hashing" | "uploading" | "done" | undefined;
export default function useFileUpload(): Uploader { export default function useFileUpload(): Uploader {
const fileUploader = useLogin().preferences.fileUploader; const fileUploader = useLogin().preferences.fileUploader;
const { publisher } = useEventPublisher(); const { publisher } = useEventPublisher();
const [progress, setProgress] = useState<Array<UploadProgress>>([]); const [progress, setProgress] = useState<Array<UploadProgress>>([]);
const [stage, setStage] = useState<UploadStage>();
switch (fileUploader) { switch (fileUploader) {
case "nostr.build": { case "nostr.build": {
@ -86,6 +90,7 @@ export default function useFileUpload(): Uploader {
id, id,
file: f, file: f,
progress: 0, progress: 0,
stage: undefined,
}, },
]); ]);
const px = (n: number) => { const px = (n: number) => {
@ -100,11 +105,12 @@ export default function useFileUpload(): Uploader {
), ),
); );
}; };
const ret = await VoidCat(f, n, publisher, px); const ret = await VoidCat(f, n, publisher, px, s => setStage(s));
setProgress(s => s.filter(a => a.id !== id)); setProgress(s => s.filter(a => a.id !== id));
return ret; return ret;
}, },
progress, progress,
stage,
} as Uploader; } as Uploader;
} }
} }

View File

@ -816,6 +816,9 @@
"TDR5ge": { "TDR5ge": {
"defaultMessage": "Media in notes will automatically be shown for selected people, otherwise only the link will show" "defaultMessage": "Media in notes will automatically be shown for selected people, otherwise only the link will show"
}, },
"TJo5E6": {
"defaultMessage": "Preview"
},
"TP/cMX": { "TP/cMX": {
"defaultMessage": "Ended" "defaultMessage": "Ended"
}, },

View File

@ -267,6 +267,7 @@
"Ss0sWu": "Pay Now", "Ss0sWu": "Pay Now",
"StKzTE": "The author has marked this note as a <i>sensitive topic</i>", "StKzTE": "The author has marked this note as a <i>sensitive topic</i>",
"TDR5ge": "Media in notes will automatically be shown for selected people, otherwise only the link will show", "TDR5ge": "Media in notes will automatically be shown for selected people, otherwise only the link will show",
"TJo5E6": "Preview",
"TP/cMX": "Ended", "TP/cMX": "Ended",
"TpgeGw": "Hex Salt..", "TpgeGw": "Hex Salt..",
"Tpy00S": "People", "Tpy00S": "People",