mirror of
https://github.com/aljazceru/rabbit.git
synced 2025-12-17 22:14:26 +01:00
feat: update translation
This commit is contained in:
@@ -4,8 +4,8 @@ type ColumnItemProps = {
|
||||
children: JSX.Element;
|
||||
};
|
||||
|
||||
const ColumnItem: Component<ColumnItemProps> = (props) => {
|
||||
return <div class="block shrink-0 overflow-hidden border-b p-1">{props.children}</div>;
|
||||
};
|
||||
const ColumnItem: Component<ColumnItemProps> = (props) => (
|
||||
<div class="block shrink-0 overflow-hidden border-b p-1">{props.children}</div>
|
||||
);
|
||||
|
||||
export default ColumnItem;
|
||||
|
||||
@@ -27,17 +27,15 @@ const tryEncodeNevent = (eventId: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
const EventLink: Component<EventLinkProps> = (props) => {
|
||||
return (
|
||||
<button class="text-blue-500 underline">
|
||||
<Show
|
||||
when={props.kind == null || props.kind === Kind.Text}
|
||||
fallback={tryEncodeNevent(props.eventId)}
|
||||
>
|
||||
{tryEncodeNote(props.eventId)}
|
||||
</Show>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
const EventLink: Component<EventLinkProps> = (props) => (
|
||||
<button class="text-blue-500 underline">
|
||||
<Show
|
||||
when={props.kind == null || props.kind === Kind.Text}
|
||||
fallback={tryEncodeNevent(props.eventId)}
|
||||
>
|
||||
{tryEncodeNote(props.eventId)}
|
||||
</Show>
|
||||
</button>
|
||||
);
|
||||
|
||||
export default EventLink;
|
||||
|
||||
@@ -260,9 +260,8 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const ensureUploaderAgreement = (): boolean => {
|
||||
return true;
|
||||
/*
|
||||
const ensureUploaderAgreement = (): boolean => true;
|
||||
/*
|
||||
if (didAgreeToToS('nostrBuild')) return true;
|
||||
|
||||
window.alert(
|
||||
@@ -277,8 +276,6 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
||||
|
||||
return didAgree;
|
||||
*/
|
||||
};
|
||||
|
||||
const handleChangeFile: JSX.EventHandler<HTMLInputElement, Event> = (ev) => {
|
||||
ev.preventDefault();
|
||||
if (uploadFilesMutation.isLoading) return;
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Component, JSX, Show, createSignal } from 'solid-js';
|
||||
|
||||
import useDetectOverflow from '@/hooks/useDetectOverflow';
|
||||
import useFormatDate from '@/hooks/useFormatDate';
|
||||
import { useTranslation } from '@/i18n/useTranslation';
|
||||
import useProfile from '@/nostr/useProfile';
|
||||
import npubEncodeFallback from '@/utils/npubEncodeFallback';
|
||||
|
||||
@@ -16,6 +17,7 @@ export type PostProps = {
|
||||
};
|
||||
|
||||
const Post: Component<PostProps> = (props) => {
|
||||
const i18n = useTranslation();
|
||||
const { overflow, elementRef } = useDetectOverflow();
|
||||
const formatDate = useFormatDate();
|
||||
|
||||
@@ -98,8 +100,8 @@ const Post: Component<PostProps> = (props) => {
|
||||
setShowOverflow((current) => !current);
|
||||
}}
|
||||
>
|
||||
<Show when={!showOverflow()} fallback="隠す">
|
||||
続きを読む
|
||||
<Show when={!showOverflow()} fallback={i18n()('post.hideOverflow')}>
|
||||
{i18n()('post.showOverflow')}
|
||||
</Show>
|
||||
</button>
|
||||
</Show>
|
||||
|
||||
@@ -5,6 +5,7 @@ import ArrowLeft from 'heroicons/24/outline/arrow-left.svg';
|
||||
import TimelineContentDisplay from '@/components/timeline/TimelineContentDisplay';
|
||||
import { TimelineContext, useTimelineState } from '@/components/timeline/TimelineContext';
|
||||
import { useHandleCommand } from '@/hooks/useCommandBus';
|
||||
import { useTranslation } from '@/i18n/useTranslation';
|
||||
|
||||
export type ColumnProps = {
|
||||
columnIndex: number;
|
||||
@@ -18,6 +19,7 @@ const Column: Component<ColumnProps> = (props) => {
|
||||
let columnDivRef: HTMLDivElement | undefined;
|
||||
|
||||
const timelineState = useTimelineState();
|
||||
const i18n = useTranslation();
|
||||
|
||||
const width = () => props.width ?? 'medium';
|
||||
|
||||
@@ -71,7 +73,7 @@ const Column: Component<ColumnProps> = (props) => {
|
||||
<div class="inline-block h-4 w-4">
|
||||
<ArrowLeft />
|
||||
</div>
|
||||
<div>ホームに戻る</div>
|
||||
<div>{i18n()('column.back')}</div>
|
||||
</button>
|
||||
</div>
|
||||
<ul class="flex h-full flex-col overflow-y-scroll scroll-smooth pb-8">
|
||||
|
||||
@@ -9,19 +9,16 @@ export type LongFormContentProps = {
|
||||
event: NostrEvent;
|
||||
};
|
||||
|
||||
const LongFormContent: Component<LongFormContentProps> = (props) => {
|
||||
const LongFormContent: Component<LongFormContentProps> = (props) => (
|
||||
// const event = () => genericEvent(props.event);
|
||||
|
||||
return (
|
||||
<button class="flex flex-col gap-1 px-1">
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="inline-block h-4 w-4 text-purple-400">
|
||||
<DocumentText />
|
||||
</span>
|
||||
<span>TODO</span>
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
<button class="flex flex-col gap-1 px-1">
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="inline-block h-4 w-4 text-purple-400">
|
||||
<DocumentText />
|
||||
</span>
|
||||
<span>TODO</span>
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
export default LongFormContent;
|
||||
|
||||
@@ -29,9 +29,7 @@ const ZapReceipt: Component<ZapReceiptProps> = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const amount = () => {
|
||||
return event().findFirstTagByName('amount');
|
||||
};
|
||||
const amount = () => event().findFirstTagByName('amount');
|
||||
|
||||
return (
|
||||
<Show when={!shouldMuteEvent(props.event)}>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createSignal, type Component, type JSX, Show } from 'solid-js';
|
||||
|
||||
import { useTranslation } from '@/i18n/useTranslation';
|
||||
import { ContentWarning } from '@/nostr/event/TextNote';
|
||||
|
||||
export type ContentWarningDisplayProps = {
|
||||
@@ -8,6 +9,7 @@ export type ContentWarningDisplayProps = {
|
||||
};
|
||||
|
||||
const ContentWarningDisplay: Component<ContentWarningDisplayProps> = (props) => {
|
||||
const i18n = useTranslation();
|
||||
const [showContentWarning, setShowContentWarning] = createSignal(false);
|
||||
|
||||
return (
|
||||
@@ -18,10 +20,12 @@ const ContentWarningDisplay: Component<ContentWarningDisplayProps> = (props) =>
|
||||
class="mt-2 w-full rounded border p-2 text-center text-xs text-stone-600 shadow-sm hover:shadow"
|
||||
onClick={() => setShowContentWarning(true)}
|
||||
>
|
||||
表示するにはクリック
|
||||
{i18n()('post.contentWarning.show')}
|
||||
<Show when={props.contentWarning.reason != null}>
|
||||
<br />
|
||||
<span>理由: {props.contentWarning.reason}</span>
|
||||
<span>
|
||||
{i18n()('post.contentWarning.reason')}: {props.contentWarning.reason}
|
||||
</span>
|
||||
</Show>
|
||||
</button>
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Component, createSignal, Show } from 'solid-js';
|
||||
|
||||
import SafeLink from '@/components/utils/SafeLink';
|
||||
import { useTranslation } from '@/i18n/useTranslation';
|
||||
import { fixUrl } from '@/utils/url';
|
||||
|
||||
type ImageDisplayProps = {
|
||||
@@ -10,6 +11,7 @@ type ImageDisplayProps = {
|
||||
|
||||
const ImageDisplay: Component<ImageDisplayProps> = (props) => {
|
||||
let imageRef: HTMLImageElement | undefined;
|
||||
const i18n = useTranslation();
|
||||
const [hidden, setHidden] = createSignal(props.initialHidden);
|
||||
|
||||
return (
|
||||
@@ -20,7 +22,7 @@ const ImageDisplay: Component<ImageDisplayProps> = (props) => {
|
||||
class="rounded bg-stone-300 p-3 text-xs text-stone-600 hover:shadow"
|
||||
onClick={() => setHidden(false)}
|
||||
>
|
||||
画像を展開する
|
||||
{i18n()('post.showImage')}
|
||||
</button>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -11,22 +11,20 @@ export type MentionedEventDisplayProps = {
|
||||
mentionedEvent: MentionedEvent;
|
||||
};
|
||||
|
||||
const MentionedEventDisplay = (props: MentionedEventDisplayProps) => {
|
||||
return (
|
||||
<Show
|
||||
when={props.mentionedEvent.marker != null && props.mentionedEvent.marker.length > 0}
|
||||
fallback={<EventLink eventId={props.mentionedEvent.eventId} />}
|
||||
>
|
||||
<div class="my-1 rounded border p-1">
|
||||
<EventDisplayById
|
||||
eventId={props.mentionedEvent.eventId}
|
||||
embedding={false}
|
||||
actions={false}
|
||||
ensureKinds={[Kind.Text]}
|
||||
/>
|
||||
</div>
|
||||
</Show>
|
||||
);
|
||||
};
|
||||
const MentionedEventDisplay = (props: MentionedEventDisplayProps) => (
|
||||
<Show
|
||||
when={props.mentionedEvent.marker != null && props.mentionedEvent.marker.length > 0}
|
||||
fallback={<EventLink eventId={props.mentionedEvent.eventId} />}
|
||||
>
|
||||
<div class="my-1 rounded border p-1">
|
||||
<EventDisplayById
|
||||
eventId={props.mentionedEvent.eventId}
|
||||
embedding={false}
|
||||
actions={false}
|
||||
ensureKinds={[Kind.Text]}
|
||||
/>
|
||||
</div>
|
||||
</Show>
|
||||
);
|
||||
|
||||
export default MentionedEventDisplay;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Component, createSignal, Show } from 'solid-js';
|
||||
|
||||
import SafeLink from '@/components/utils/SafeLink';
|
||||
import { useTranslation } from '@/i18n/useTranslation';
|
||||
|
||||
type VideoDisplayProps = {
|
||||
url: string;
|
||||
@@ -9,6 +10,7 @@ type VideoDisplayProps = {
|
||||
|
||||
const VideoDisplay: Component<VideoDisplayProps> = (props) => {
|
||||
let videoRef: HTMLVideoElement | undefined;
|
||||
const i18n = useTranslation();
|
||||
const [hidden, setHidden] = createSignal(props.initialHidden);
|
||||
|
||||
return (
|
||||
@@ -19,7 +21,7 @@ const VideoDisplay: Component<VideoDisplayProps> = (props) => {
|
||||
class="rounded bg-stone-300 p-3 text-xs text-stone-600 hover:shadow"
|
||||
onClick={() => setHidden(false)}
|
||||
>
|
||||
動画を表示する
|
||||
{i18n()('post.showVideo')}
|
||||
</button>
|
||||
}
|
||||
>
|
||||
@@ -31,7 +33,7 @@ const VideoDisplay: Component<VideoDisplayProps> = (props) => {
|
||||
src={props.url}
|
||||
controls
|
||||
>
|
||||
<a href={props.url}>ダウンロード</a>
|
||||
<a href={props.url}>{i18n()('post.download')}</a>
|
||||
</video>
|
||||
</SafeLink>
|
||||
</Show>
|
||||
|
||||
@@ -109,18 +109,16 @@ const About: Component<AboutProps> = (props) => {
|
||||
<h2 class="my-4 text-xl font-bold">使用ライブラリ</h2>
|
||||
|
||||
<For each={packageInfo()?.packages ?? []} fallback="取得中">
|
||||
{(p) => {
|
||||
return (
|
||||
<>
|
||||
<h3 class="mb-2 mt-4 font-mono">
|
||||
{p.name}@{p.version} ({p.licenseSpdx})
|
||||
</h3>
|
||||
<pre class="max-h-96 overflow-scroll rounded bg-zinc-100 p-4 text-xs">
|
||||
{p.licenseText}
|
||||
</pre>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
{(p) => (
|
||||
<>
|
||||
<h3 class="mb-2 mt-4 font-mono">
|
||||
{p.name}@{p.version} ({p.licenseSpdx})
|
||||
</h3>
|
||||
<pre class="max-h-96 overflow-scroll rounded bg-zinc-100 p-4 text-xs">
|
||||
{p.licenseText}
|
||||
</pre>
|
||||
</>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
</BasicModal>
|
||||
|
||||
@@ -10,27 +10,25 @@ export type BasicModalProps = {
|
||||
children: JSX.Element;
|
||||
};
|
||||
|
||||
const BasicModal: Component<BasicModalProps> = (props) => {
|
||||
return (
|
||||
<Modal onClose={() => props.onClose?.()}>
|
||||
<div class="w-[640px] max-w-full">
|
||||
<button
|
||||
class="w-full pt-1 text-start text-stone-800"
|
||||
aria-label="Close"
|
||||
onClick={() => props.onClose?.()}
|
||||
>
|
||||
<span class="inline-block h-8 w-8">
|
||||
<Show when={props?.closeButton} fallback={<XMark />} keyed>
|
||||
{(button) => button()}
|
||||
</Show>
|
||||
</span>
|
||||
</button>
|
||||
<div class="flex max-h-[calc(100vh-4em)] flex-col overflow-y-scroll rounded-xl border bg-white text-stone-700 shadow-lg">
|
||||
{props.children}
|
||||
</div>
|
||||
const BasicModal: Component<BasicModalProps> = (props) => (
|
||||
<Modal onClose={() => props.onClose?.()}>
|
||||
<div class="w-[640px] max-w-full">
|
||||
<button
|
||||
class="w-full pt-1 text-start text-stone-800"
|
||||
aria-label="Close"
|
||||
onClick={() => props.onClose?.()}
|
||||
>
|
||||
<span class="inline-block h-8 w-8">
|
||||
<Show when={props?.closeButton} fallback={<XMark />} keyed>
|
||||
{(button) => button()}
|
||||
</Show>
|
||||
</span>
|
||||
</button>
|
||||
<div class="flex max-h-[calc(100vh-4em)] flex-col overflow-y-scroll rounded-xl border bg-white text-stone-700 shadow-lg">
|
||||
{props.children}
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
export default BasicModal;
|
||||
|
||||
@@ -104,16 +104,14 @@ const RelayConfig = () => {
|
||||
</p>
|
||||
<ul>
|
||||
<For each={config().relayUrls}>
|
||||
{(relayUrl: string) => {
|
||||
return (
|
||||
<li class="flex items-center">
|
||||
<div class="flex-1 truncate">{relayUrl}</div>
|
||||
<button class="h-3 w-3 shrink-0" onClick={() => removeRelay(relayUrl)}>
|
||||
<XMark />
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
}}
|
||||
{(relayUrl: string) => (
|
||||
<li class="flex items-center">
|
||||
<div class="flex-1 truncate">{relayUrl}</div>
|
||||
<button class="h-3 w-3 shrink-0" onClick={() => removeRelay(relayUrl)}>
|
||||
<XMark />
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
</For>
|
||||
</ul>
|
||||
<form class="flex gap-2" onSubmit={handleClickAddRelay}>
|
||||
@@ -211,23 +209,21 @@ const DateFormatConfig = () => {
|
||||
const ToggleButton = (props: {
|
||||
value: boolean;
|
||||
onClick: JSX.EventHandler<HTMLButtonElement, MouseEvent>;
|
||||
}) => {
|
||||
return (
|
||||
<button
|
||||
class="flex h-[24px] w-[48px] items-center rounded-full border border-primary px-1"
|
||||
classList={{
|
||||
'bg-white': !props.value,
|
||||
'justify-start': !props.value,
|
||||
'bg-rose-300': props.value,
|
||||
'justify-end': props.value,
|
||||
}}
|
||||
area-label={props.value}
|
||||
onClick={(event) => props.onClick(event)}
|
||||
>
|
||||
<span class="m-[-2px] inline-block h-5 w-5 rounded-full border border-primary bg-white shadow" />
|
||||
</button>
|
||||
);
|
||||
};
|
||||
}) => (
|
||||
<button
|
||||
class="flex h-[24px] w-[48px] items-center rounded-full border border-primary px-1"
|
||||
classList={{
|
||||
'bg-white': !props.value,
|
||||
'justify-start': !props.value,
|
||||
'bg-rose-300': props.value,
|
||||
'justify-end': props.value,
|
||||
}}
|
||||
area-label={props.value}
|
||||
onClick={(event) => props.onClick(event)}
|
||||
>
|
||||
<span class="m-[-2px] inline-block h-5 w-5 rounded-full border border-primary bg-white shadow" />
|
||||
</button>
|
||||
);
|
||||
|
||||
const ReactionConfig = () => {
|
||||
const i18n = useTranslation();
|
||||
|
||||
@@ -39,14 +39,12 @@ const RepliesDisplay: Component<{ event: NostrEvent }> = (props) => {
|
||||
return <Timeline events={[...events()].reverse()} />;
|
||||
};
|
||||
|
||||
const TimelineContentDisplay: Component<{ timelineContent: TimelineContent }> = (props) => {
|
||||
return (
|
||||
<Switch>
|
||||
<Match when={props.timelineContent.type === 'Replies' && props.timelineContent} keyed>
|
||||
{(replies) => <RepliesDisplay event={replies.event} />}
|
||||
</Match>
|
||||
</Switch>
|
||||
);
|
||||
};
|
||||
const TimelineContentDisplay: Component<{ timelineContent: TimelineContent }> = (props) => (
|
||||
<Switch>
|
||||
<Match when={props.timelineContent.type === 'Replies' && props.timelineContent} keyed>
|
||||
{(replies) => <RepliesDisplay event={replies.event} />}
|
||||
</Match>
|
||||
</Switch>
|
||||
);
|
||||
|
||||
export default TimelineContentDisplay;
|
||||
|
||||
@@ -34,6 +34,6 @@ export const useTranslation = () => {
|
||||
return i18nextFn;
|
||||
};
|
||||
|
||||
export const I18NextProvider: Component<I18NextProviderProps> = (props) => {
|
||||
return <I18NextContext.Provider value={props.i18next}>{props.children}</I18NextContext.Provider>;
|
||||
};
|
||||
export const I18NextProvider: Component<I18NextProviderProps> = (props) => (
|
||||
<I18NextContext.Provider value={props.i18next}>{props.children}</I18NextContext.Provider>
|
||||
);
|
||||
|
||||
@@ -23,6 +23,7 @@ export default {
|
||||
search: 'Search',
|
||||
myPosts: 'My posts',
|
||||
myReactions: 'My reactions',
|
||||
back: 'Back',
|
||||
config: {
|
||||
columnWidth: 'Column width',
|
||||
widest: 'Widest',
|
||||
@@ -61,6 +62,15 @@ export default {
|
||||
deletedSuccessfully: 'Deleted successfully (reload to reflect)',
|
||||
failedToDeletePartially: 'Failed to delete on {{count}} relays',
|
||||
failedToDelete: 'Failed to delete',
|
||||
showImage: 'Show image',
|
||||
showVideo: 'Show video',
|
||||
showOverflow: 'Read more',
|
||||
hideOverflow: 'Hide',
|
||||
download: 'Download',
|
||||
contentWarning: {
|
||||
show: 'Click to display',
|
||||
reason: 'Reason',
|
||||
},
|
||||
},
|
||||
notification: {
|
||||
reposted: ' reposted',
|
||||
|
||||
@@ -21,6 +21,7 @@ export default {
|
||||
search: '検索',
|
||||
myPosts: '自分の投稿',
|
||||
myReactions: '自分のリアクション',
|
||||
back: '戻る',
|
||||
config: {
|
||||
columnWidth: 'カラム幅',
|
||||
widest: '特大',
|
||||
@@ -59,6 +60,15 @@ export default {
|
||||
deletedSuccessfully: '削除しました(画面への反映にはリロード)',
|
||||
failedToDeletePartially: '{{count}}個のリレーで削除に失敗しました',
|
||||
failedToDelete: 'すべてのリレーで削除に失敗しました',
|
||||
showImage: '画像を表示する',
|
||||
showVideo: '動画を表示する',
|
||||
showOverflow: '続きを読む',
|
||||
hideOverflow: '隠す',
|
||||
download: 'ダウンロード',
|
||||
contentWarning: {
|
||||
show: '表示するにはクリック',
|
||||
reason: '理由',
|
||||
},
|
||||
},
|
||||
notification: {
|
||||
reposted: 'がリポスト',
|
||||
|
||||
@@ -3,10 +3,6 @@ import { Kind, Event as NostrEvent } from 'nostr-tools';
|
||||
import GenericEvent from '@/nostr/event/GenericEvent';
|
||||
import TextNote from '@/nostr/event/TextNote';
|
||||
|
||||
export const genericEvent = (event: NostrEvent): GenericEvent => {
|
||||
return new GenericEvent(event);
|
||||
};
|
||||
export const genericEvent = (event: NostrEvent): GenericEvent => new GenericEvent(event);
|
||||
|
||||
export const textNote = (event: NostrEvent): TextNote => {
|
||||
return new TextNote(event);
|
||||
};
|
||||
export const textNote = (event: NostrEvent): TextNote => new TextNote(event);
|
||||
|
||||
@@ -23,8 +23,8 @@ export type PublishTextNoteParams = {
|
||||
} & TagParams;
|
||||
|
||||
// NIP-20: Command Result
|
||||
const waitCommandResult = (pub: Pub, relayUrl: string): Promise<void> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const waitCommandResult = (pub: Pub, relayUrl: string): Promise<void> =>
|
||||
new Promise((resolve, reject) => {
|
||||
pub.on('ok', () => {
|
||||
console.log(`${relayUrl} has accepted our event`);
|
||||
resolve();
|
||||
@@ -34,7 +34,6 @@ const waitCommandResult = (pub: Pub, relayUrl: string): Promise<void> => {
|
||||
reject(reason);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const buildTags = ({
|
||||
notifyPubkeys,
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import type { Component } from 'solid-js';
|
||||
|
||||
const NotFound: Component = () => {
|
||||
return (
|
||||
<div class="container mx-auto max-w-[640px] py-10">
|
||||
<h1 class="text-4xl font-bold text-stone-700">お探しのページは見つかりませんでした</h1>
|
||||
<p class="pt-4">
|
||||
<a class="text-blue-500 underline" href="/">
|
||||
← トップに戻る
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const NotFound: Component = () => (
|
||||
<div class="container mx-auto max-w-[640px] py-10">
|
||||
<h1 class="text-4xl font-bold text-stone-700">お探しのページは見つかりませんでした</h1>
|
||||
<p class="pt-4">
|
||||
<a class="text-blue-500 underline" href="/">
|
||||
← トップに戻る
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default NotFound;
|
||||
|
||||
@@ -74,6 +74,5 @@ export type UploaderIds = keyof typeof uploaders;
|
||||
|
||||
export const uploadFiles =
|
||||
<T>(uploadFn: (file: Blob) => Promise<T>) =>
|
||||
(files: File[]): Promise<PromiseSettledResult<Awaited<T>>[]> => {
|
||||
return Promise.allSettled(files.map((file) => uploadFn(file)));
|
||||
};
|
||||
(files: File[]): Promise<PromiseSettledResult<Awaited<T>>[]> =>
|
||||
Promise.allSettled(files.map((file) => uploadFn(file)));
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const sleep = (ms: number): Promise<void> => {
|
||||
return new Promise((resolve) => {
|
||||
const sleep = (ms: number): Promise<void> =>
|
||||
new Promise((resolve) => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
};
|
||||
|
||||
export default sleep;
|
||||
|
||||
Reference in New Issue
Block a user