mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-28 18:53:47 +01:00
Add option to mirror blobs when sharing notes
This commit is contained in:
parent
c88e2df5f0
commit
ab394aa6e3
5
.changeset/happy-penguins-check.md
Normal file
5
.changeset/happy-penguins-check.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"nostrudel": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add option to mirror blobs when sharing notes
|
@ -142,7 +142,7 @@
|
|||||||
"@capacitor/core": "^6.2.0",
|
"@capacitor/core": "^6.2.0",
|
||||||
"@capacitor/ios": "^6.2.0",
|
"@capacitor/ios": "^6.2.0",
|
||||||
"@capacitor/preferences": "^6.0.3",
|
"@capacitor/preferences": "^6.0.3",
|
||||||
"@changesets/cli": "^2.27.11",
|
"@changesets/cli": "^2.27.12",
|
||||||
"@types/canvas-confetti": "^1.9.0",
|
"@types/canvas-confetti": "^1.9.0",
|
||||||
"@types/chroma-js": "^2.4.5",
|
"@types/chroma-js": "^2.4.5",
|
||||||
"@types/debug": "^4.1.12",
|
"@types/debug": "^4.1.12",
|
||||||
|
928
pnpm-lock.yaml
generated
928
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,17 +0,0 @@
|
|||||||
import { memo } from "react";
|
|
||||||
import { verifyEvent } from "nostr-tools";
|
|
||||||
|
|
||||||
import { NostrEvent } from "../../types/nostr-event";
|
|
||||||
import { CheckIcon, VerificationFailed } from "../icons";
|
|
||||||
import useAppSettings from "../../hooks/use-user-app-settings";
|
|
||||||
|
|
||||||
function EventVerificationIcon({ event }: { event: NostrEvent }) {
|
|
||||||
const { showSignatureVerification } = useAppSettings();
|
|
||||||
if (!showSignatureVerification) return null;
|
|
||||||
|
|
||||||
if (!verifyEvent(event)) {
|
|
||||||
return <VerificationFailed color="red.500" />;
|
|
||||||
}
|
|
||||||
return <CheckIcon color="green.500" />;
|
|
||||||
}
|
|
||||||
export default memo(EventVerificationIcon);
|
|
@ -5,17 +5,14 @@ import { Link as RouterLink, useNavigate } from "react-router-dom";
|
|||||||
import { NostrEvent } from "../../../types/nostr-event";
|
import { NostrEvent } from "../../../types/nostr-event";
|
||||||
import UserAvatarLink from "../../user/user-avatar-link";
|
import UserAvatarLink from "../../user/user-avatar-link";
|
||||||
import UserLink from "../../user/user-link";
|
import UserLink from "../../user/user-link";
|
||||||
import EventVerificationIcon from "../../common-event/event-verification-icon";
|
|
||||||
import { TrustProvider } from "../../../providers/local/trust-provider";
|
import { TrustProvider } from "../../../providers/local/trust-provider";
|
||||||
import { NoteLink } from "../../note/note-link";
|
import { NoteLink } from "../../note/note-link";
|
||||||
import Timestamp from "../../timestamp";
|
import Timestamp from "../../timestamp";
|
||||||
import { CompactNoteContent } from "../../compact-note-content";
|
import { CompactNoteContent } from "../../compact-note-content";
|
||||||
import HoverLinkOverlay from "../../hover-link-overlay";
|
import HoverLinkOverlay from "../../hover-link-overlay";
|
||||||
import { getSharableEventAddress } from "../../../services/relay-hints";
|
import { getSharableEventAddress } from "../../../services/relay-hints";
|
||||||
import useAppSettings from "../../../hooks/use-user-app-settings";
|
|
||||||
|
|
||||||
export default function EmbeddedNote({ event, ...props }: Omit<CardProps, "children"> & { event: NostrEvent }) {
|
export default function EmbeddedNote({ event, ...props }: Omit<CardProps, "children"> & { event: NostrEvent }) {
|
||||||
const { showSignatureVerification } = useAppSettings();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const to = `/n/${getSharableEventAddress(event)}`;
|
const to = `/n/${getSharableEventAddress(event)}`;
|
||||||
|
|
||||||
@ -38,7 +35,6 @@ export default function EmbeddedNote({ event, ...props }: Omit<CardProps, "child
|
|||||||
</NoteLink>
|
</NoteLink>
|
||||||
<HoverLinkOverlay as={RouterLink} to={to} onClick={handleClick} />
|
<HoverLinkOverlay as={RouterLink} to={to} onClick={handleClick} />
|
||||||
<Spacer />
|
<Spacer />
|
||||||
{showSignatureVerification && <EventVerificationIcon event={event} />}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
<CompactNoteContent px="2" event={event} maxLength={96} />
|
<CompactNoteContent px="2" event={event} maxLength={96} />
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { MouseEventHandler, useCallback } from "react";
|
||||||
import { Card, CardProps, Flex, LinkBox, Spacer, Text } from "@chakra-ui/react";
|
import { Card, CardProps, Flex, LinkBox, Spacer, Text } from "@chakra-ui/react";
|
||||||
import { Link as RouterLink, useNavigate } from "react-router-dom";
|
import { Link as RouterLink, useNavigate } from "react-router-dom";
|
||||||
import { nip19 } from "nostr-tools";
|
import { nip19 } from "nostr-tools";
|
||||||
@ -5,7 +6,6 @@ import { nip19 } from "nostr-tools";
|
|||||||
import { NostrEvent } from "../../../types/nostr-event";
|
import { NostrEvent } from "../../../types/nostr-event";
|
||||||
import UserAvatarLink from "../../user/user-avatar-link";
|
import UserAvatarLink from "../../user/user-avatar-link";
|
||||||
import UserLink from "../../user/user-link";
|
import UserLink from "../../user/user-link";
|
||||||
import EventVerificationIcon from "../../common-event/event-verification-icon";
|
|
||||||
import { TrustProvider } from "../../../providers/local/trust-provider";
|
import { TrustProvider } from "../../../providers/local/trust-provider";
|
||||||
import Timestamp from "../../timestamp";
|
import Timestamp from "../../timestamp";
|
||||||
import { CompactNoteContent } from "../../compact-note-content";
|
import { CompactNoteContent } from "../../compact-note-content";
|
||||||
@ -13,15 +13,12 @@ import HoverLinkOverlay from "../../hover-link-overlay";
|
|||||||
import { getThreadReferences } from "../../../helpers/nostr/event";
|
import { getThreadReferences } from "../../../helpers/nostr/event";
|
||||||
import useSingleEvent from "../../../hooks/use-single-event";
|
import useSingleEvent from "../../../hooks/use-single-event";
|
||||||
import { getTorrentTitle } from "../../../helpers/nostr/torrents";
|
import { getTorrentTitle } from "../../../helpers/nostr/torrents";
|
||||||
import { MouseEventHandler, useCallback } from "react";
|
|
||||||
import useAppSettings from "../../../hooks/use-user-app-settings";
|
|
||||||
|
|
||||||
export default function EmbeddedTorrentComment({
|
export default function EmbeddedTorrentComment({
|
||||||
comment,
|
comment,
|
||||||
...props
|
...props
|
||||||
}: Omit<CardProps, "children"> & { comment: NostrEvent }) {
|
}: Omit<CardProps, "children"> & { comment: NostrEvent }) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { showSignatureVerification } = useAppSettings();
|
|
||||||
const refs = getThreadReferences(comment);
|
const refs = getThreadReferences(comment);
|
||||||
const torrent = useSingleEvent(refs.root?.e?.id, refs.root?.e?.relays);
|
const torrent = useSingleEvent(refs.root?.e?.id, refs.root?.e?.relays);
|
||||||
const linkToTorrent = refs.root?.e && `/torrents/${nip19.neventEncode(refs.root.e)}`;
|
const linkToTorrent = refs.root?.e && `/torrents/${nip19.neventEncode(refs.root.e)}`;
|
||||||
@ -45,7 +42,6 @@ export default function EmbeddedTorrentComment({
|
|||||||
{torrent ? getTorrentTitle(torrent) : "torrent"}
|
{torrent ? getTorrentTitle(torrent) : "torrent"}
|
||||||
</HoverLinkOverlay>
|
</HoverLinkOverlay>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
{showSignatureVerification && <EventVerificationIcon event={comment} />}
|
|
||||||
<Timestamp timestamp={comment.created_at} />
|
<Timestamp timestamp={comment.created_at} />
|
||||||
</Flex>
|
</Flex>
|
||||||
<CompactNoteContent px="2" event={comment} maxLength={96} />
|
<CompactNoteContent px="2" event={comment} maxLength={96} />
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { useState } from "react";
|
import { useMemo, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
Center,
|
||||||
|
Checkbox,
|
||||||
Modal,
|
Modal,
|
||||||
ModalBody,
|
ModalBody,
|
||||||
ModalCloseButton,
|
ModalCloseButton,
|
||||||
@ -9,12 +11,22 @@ import {
|
|||||||
ModalHeader,
|
ModalHeader,
|
||||||
ModalOverlay,
|
ModalOverlay,
|
||||||
ModalProps,
|
ModalProps,
|
||||||
|
Spinner,
|
||||||
|
Text,
|
||||||
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { NostrEvent } from "nostr-tools";
|
import { NostrEvent } from "nostr-tools";
|
||||||
import { useEventFactory } from "applesauce-react/hooks";
|
import { useEventFactory } from "applesauce-react/hooks";
|
||||||
|
import { getMediaAttachments } from "applesauce-core/helpers";
|
||||||
|
import { getMediaAttachmentURLsFromContent } from "applesauce-content/helpers";
|
||||||
|
import { BlossomClient } from "blossom-client-sdk";
|
||||||
|
|
||||||
import { usePublishEvent } from "../../../../providers/global/publish-provider";
|
import { usePublishEvent } from "../../../../providers/global/publish-provider";
|
||||||
import { EmbedEvent } from "../../../embed-event";
|
import { EmbedEvent } from "../../../embed-event";
|
||||||
|
import useAppSettings from "../../../../hooks/use-user-app-settings";
|
||||||
|
import useUsersMediaServers from "../../../../hooks/use-user-media-servers";
|
||||||
|
import useCurrentAccount from "../../../../hooks/use-current-account";
|
||||||
|
import { useSigningContext } from "../../../../providers/global/signing-provider";
|
||||||
|
|
||||||
export default function ShareModal({
|
export default function ShareModal({
|
||||||
event,
|
event,
|
||||||
@ -22,17 +34,76 @@ export default function ShareModal({
|
|||||||
onClose,
|
onClose,
|
||||||
...props
|
...props
|
||||||
}: Omit<ModalProps, "children"> & { event: NostrEvent }) {
|
}: Omit<ModalProps, "children"> & { event: NostrEvent }) {
|
||||||
|
const { mirrorBlobsOnShare } = useAppSettings();
|
||||||
|
const account = useCurrentAccount();
|
||||||
const publish = usePublishEvent();
|
const publish = usePublishEvent();
|
||||||
const factory = useEventFactory();
|
const factory = useEventFactory();
|
||||||
|
const toast = useToast();
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const { requestSignature } = useSigningContext();
|
||||||
|
const { servers } = useUsersMediaServers(account?.pubkey);
|
||||||
|
const [mirror, setMirror] = useState(mirrorBlobsOnShare);
|
||||||
|
const mediaAttachments = useMemo(() => {
|
||||||
|
const attachments = getMediaAttachments(event)
|
||||||
|
// filter out media attachments without hashes
|
||||||
|
.filter((media) => !!media.sha256);
|
||||||
|
|
||||||
|
// extra media attachments from content
|
||||||
|
const content = getMediaAttachmentURLsFromContent(event.content)
|
||||||
|
// remove duplicates
|
||||||
|
.filter((media) => !attachments.some((a) => a.sha256 === media.sha256));
|
||||||
|
|
||||||
|
return [...attachments, ...content];
|
||||||
|
}, [event]);
|
||||||
|
|
||||||
|
const canMirror = servers.length > 0 && mediaAttachments.length > 0;
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState("");
|
||||||
const share = async () => {
|
const share = async () => {
|
||||||
setLoading(true);
|
if (mirror && canMirror) {
|
||||||
|
try {
|
||||||
|
setLoading("Requesting signature for mirroring...");
|
||||||
|
const auth = await BlossomClient.createUploadAuth(
|
||||||
|
requestSignature,
|
||||||
|
mediaAttachments.filter((m) => !!m.sha256).map((m) => m.sha256!),
|
||||||
|
);
|
||||||
|
|
||||||
|
setLoading("Mirror blobs...");
|
||||||
|
for (const media of mediaAttachments) {
|
||||||
|
// send mirror request to all servers
|
||||||
|
await Promise.allSettled(
|
||||||
|
servers.map((server) =>
|
||||||
|
BlossomClient.mirrorBlob(
|
||||||
|
server,
|
||||||
|
{
|
||||||
|
sha256: media.sha256!,
|
||||||
|
url: media.url,
|
||||||
|
// TODO: these are not needed and should be removed
|
||||||
|
uploaded: 0,
|
||||||
|
size: media.size ?? 0,
|
||||||
|
},
|
||||||
|
{ auth },
|
||||||
|
).catch((err) => {
|
||||||
|
// ignore errors from individual servers
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error)
|
||||||
|
toast({ status: "error", title: `Failed to mirror media`, description: error.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading("Sharing...");
|
||||||
const draft = await factory.share(event);
|
const draft = await factory.share(event);
|
||||||
|
|
||||||
|
setLoading("Publishing...");
|
||||||
await publish("Share", draft);
|
await publish("Share", draft);
|
||||||
|
setLoading("");
|
||||||
|
|
||||||
|
// close modal
|
||||||
onClose();
|
onClose();
|
||||||
setLoading(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -44,7 +115,26 @@ export default function ShareModal({
|
|||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
<ModalCloseButton />
|
<ModalCloseButton />
|
||||||
<ModalBody px="4" py="0">
|
<ModalBody px="4" py="0">
|
||||||
<EmbedEvent event={event} />
|
{loading ? (
|
||||||
|
<Center>
|
||||||
|
<Spinner /> {loading}
|
||||||
|
</Center>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<EmbedEvent event={event} />
|
||||||
|
|
||||||
|
{canMirror && (
|
||||||
|
<>
|
||||||
|
<Checkbox isChecked={mirror} onChange={() => setMirror(!mirror)} mt="4">
|
||||||
|
Mirror media ({mediaAttachments.length}) to blossom servers ({servers.length})
|
||||||
|
</Checkbox>
|
||||||
|
<Text fontSize="sm" color="GrayText">
|
||||||
|
Copy media to your blossom servers so it can be found later
|
||||||
|
</Text>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
<ModalFooter px="4" py="4">
|
<ModalFooter px="4" py="4">
|
||||||
@ -56,7 +146,7 @@ export default function ShareModal({
|
|||||||
variant="solid"
|
variant="solid"
|
||||||
onClick={() => share()}
|
onClick={() => share()}
|
||||||
size="md"
|
size="md"
|
||||||
isLoading={loading}
|
isLoading={!!loading}
|
||||||
flexShrink={0}
|
flexShrink={0}
|
||||||
>
|
>
|
||||||
Share
|
Share
|
||||||
|
@ -22,7 +22,6 @@ import NoteMenu from "../note-menu";
|
|||||||
import UserLink from "../../user/user-link";
|
import UserLink from "../../user/user-link";
|
||||||
import EventZapButton from "../../zap/event-zap-button";
|
import EventZapButton from "../../zap/event-zap-button";
|
||||||
import { ExpandProvider } from "../../../providers/local/expanded";
|
import { ExpandProvider } from "../../../providers/local/expanded";
|
||||||
import EventVerificationIcon from "../../common-event/event-verification-icon";
|
|
||||||
import EventShareButton from "./components/event-share-button";
|
import EventShareButton from "./components/event-share-button";
|
||||||
import EventQuoteButton from "../event-quote-button";
|
import EventQuoteButton from "../event-quote-button";
|
||||||
import { ReplyIcon } from "../../icons";
|
import { ReplyIcon } from "../../icons";
|
||||||
@ -67,7 +66,7 @@ export function TimelineNote({
|
|||||||
...props
|
...props
|
||||||
}: TimelineNoteProps) {
|
}: TimelineNoteProps) {
|
||||||
const account = useCurrentAccount();
|
const account = useCurrentAccount();
|
||||||
const { showReactions, showSignatureVerification } = useAppSettings();
|
const { showReactions } = useAppSettings();
|
||||||
const hideZapBubbles = useObservable(localSettings.hideZapBubbles);
|
const hideZapBubbles = useObservable(localSettings.hideZapBubbles);
|
||||||
const replyForm = useDisclosure();
|
const replyForm = useDisclosure();
|
||||||
|
|
||||||
@ -98,7 +97,6 @@ export function TimelineNote({
|
|||||||
<POWIcon event={event} boxSize={5} />
|
<POWIcon event={event} boxSize={5} />
|
||||||
<NotePublishedUsing event={event} />
|
<NotePublishedUsing event={event} />
|
||||||
<Flex grow={1} />
|
<Flex grow={1} />
|
||||||
{showSignatureVerification && <EventVerificationIcon event={event} />}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
<NoteCommunityMetadata event={event} />
|
<NoteCommunityMetadata event={event} />
|
||||||
{showReplyLine && <ReplyContext event={event} />}
|
{showReplyLine && <ReplyContext event={event} />}
|
||||||
|
@ -4,7 +4,7 @@ import { kinds } from "nostr-tools";
|
|||||||
export const APP_SETTINGS_KIND = kinds.Application;
|
export const APP_SETTINGS_KIND = kinds.Application;
|
||||||
export const APP_SETTING_IDENTIFIER = "nostrudel-settings";
|
export const APP_SETTING_IDENTIFIER = "nostrudel-settings";
|
||||||
|
|
||||||
export type AppSettingsV0 = {
|
type AppSettingsV0 = {
|
||||||
version: 0;
|
version: 0;
|
||||||
colorMode: ColorModeWithSystem;
|
colorMode: ColorModeWithSystem;
|
||||||
defaultRelays: string[];
|
defaultRelays: string[];
|
||||||
@ -12,7 +12,6 @@ export type AppSettingsV0 = {
|
|||||||
autoShowMedia: boolean;
|
autoShowMedia: boolean;
|
||||||
proxyUserMedia: boolean;
|
proxyUserMedia: boolean;
|
||||||
showReactions: boolean;
|
showReactions: boolean;
|
||||||
/** @deprecated */
|
|
||||||
showSignatureVerification: boolean;
|
showSignatureVerification: boolean;
|
||||||
|
|
||||||
autoPayWithWebLN: boolean;
|
autoPayWithWebLN: boolean;
|
||||||
@ -26,36 +25,41 @@ export type AppSettingsV0 = {
|
|||||||
redditRedirect?: string;
|
redditRedirect?: string;
|
||||||
youtubeRedirect?: string;
|
youtubeRedirect?: string;
|
||||||
};
|
};
|
||||||
export type AppSettingsV1 = Omit<AppSettingsV0, "version"> & {
|
type AppSettingsV1 = Omit<AppSettingsV0, "version"> & {
|
||||||
version: 1;
|
version: 1;
|
||||||
mutedWords?: string;
|
mutedWords?: string;
|
||||||
maxPageWidth: "none" | "sm" | "md" | "lg" | "xl" | "full";
|
maxPageWidth: "none" | "sm" | "md" | "lg" | "xl" | "full";
|
||||||
};
|
};
|
||||||
export type AppSettingsV2 = Omit<AppSettingsV1, "version"> & { version: 2; theme: string };
|
type AppSettingsV2 = Omit<AppSettingsV1, "version"> & { version: 2; theme: string };
|
||||||
export type AppSettingsV3 = Omit<AppSettingsV2, "version"> & { version: 3; quickReactions: string[] };
|
type AppSettingsV3 = Omit<AppSettingsV2, "version"> & { version: 3; quickReactions: string[] };
|
||||||
export type AppSettingsV4 = Omit<AppSettingsV3, "version"> & { version: 4; loadOpenGraphData: boolean };
|
type AppSettingsV4 = Omit<AppSettingsV3, "version"> & { version: 4; loadOpenGraphData: boolean };
|
||||||
export type AppSettingsV5 = Omit<AppSettingsV4, "version"> & { version: 5; hideUsernames: boolean };
|
type AppSettingsV5 = Omit<AppSettingsV4, "version"> & { version: 5; hideUsernames: boolean };
|
||||||
export type AppSettingsV6 = Omit<AppSettingsV5, "version"> & { version: 6; noteDifficulty: number | null };
|
type AppSettingsV6 = Omit<AppSettingsV5, "version"> & { version: 6; noteDifficulty: number | null };
|
||||||
export type AppSettingsV7 = Omit<AppSettingsV6, "version"> & { version: 7; autoDecryptDMs: boolean };
|
type AppSettingsV7 = Omit<AppSettingsV6, "version"> & { version: 7; autoDecryptDMs: boolean };
|
||||||
export type AppSettingsV8 = Omit<AppSettingsV7, "version"> & {
|
type AppSettingsV8 = Omit<AppSettingsV7, "version"> & {
|
||||||
version: 8;
|
version: 8;
|
||||||
mediaUploadService: "nostr.build" | "blossom";
|
mediaUploadService: "nostr.build" | "blossom";
|
||||||
};
|
};
|
||||||
export type AppSettingsV9 = Omit<AppSettingsV8, "version"> & { version: 9; removeEmojisInUsernames: boolean };
|
type AppSettingsV9 = Omit<AppSettingsV8, "version"> & { version: 9; removeEmojisInUsernames: boolean };
|
||||||
|
|
||||||
export type AppSettingsV10 = Omit<AppSettingsV9, "version" | "defaultRelays"> & {
|
type AppSettingsV10 = Omit<AppSettingsV9, "version" | "defaultRelays"> & {
|
||||||
version: 10;
|
version: 10;
|
||||||
showPubkeyColor: "none" | "avatar" | "underline";
|
showPubkeyColor: "none" | "avatar" | "underline";
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AppSettingsV11 = Omit<AppSettingsV10, "quickReactions" | "version"> & {
|
type AppSettingsV11 = Omit<AppSettingsV10, "quickReactions" | "version"> & {
|
||||||
version: 11;
|
version: 11;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AppSettings = AppSettingsV11;
|
type AppSettingsV12 = Omit<AppSettingsV11, "showSignatureVerification" | "version"> & {
|
||||||
|
version: 12;
|
||||||
|
mirrorBlobsOnShare: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AppSettings = AppSettingsV12;
|
||||||
|
|
||||||
export const defaultSettings: AppSettings = {
|
export const defaultSettings: AppSettings = {
|
||||||
version: 11,
|
version: 12,
|
||||||
|
|
||||||
// display
|
// display
|
||||||
theme: "default",
|
theme: "default",
|
||||||
@ -69,12 +73,11 @@ export const defaultSettings: AppSettings = {
|
|||||||
autoShowMedia: true,
|
autoShowMedia: true,
|
||||||
showContentWarning: true,
|
showContentWarning: true,
|
||||||
loadOpenGraphData: true,
|
loadOpenGraphData: true,
|
||||||
/** @deprecated */
|
|
||||||
showSignatureVerification: false,
|
|
||||||
|
|
||||||
// posting
|
// posting
|
||||||
noteDifficulty: null,
|
noteDifficulty: null,
|
||||||
proxyUserMedia: false,
|
proxyUserMedia: false,
|
||||||
|
mirrorBlobsOnShare: false,
|
||||||
|
|
||||||
// performance
|
// performance
|
||||||
showReactions: true,
|
showReactions: true,
|
||||||
|
@ -12,7 +12,6 @@ import {
|
|||||||
AlertIcon,
|
AlertIcon,
|
||||||
AlertTitle,
|
AlertTitle,
|
||||||
AlertDescription,
|
AlertDescription,
|
||||||
Heading,
|
|
||||||
Switch,
|
Switch,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { useObservable } from "applesauce-react/hooks";
|
import { useObservable } from "applesauce-react/hooks";
|
||||||
@ -20,7 +19,6 @@ import { useObservable } from "applesauce-react/hooks";
|
|||||||
import useUsersMediaServers from "../../../hooks/use-user-media-servers";
|
import useUsersMediaServers from "../../../hooks/use-user-media-servers";
|
||||||
import useCurrentAccount from "../../../hooks/use-current-account";
|
import useCurrentAccount from "../../../hooks/use-current-account";
|
||||||
import useSettingsForm from "../use-settings-form";
|
import useSettingsForm from "../use-settings-form";
|
||||||
import VerticalPageLayout from "../../../components/vertical-page-layout";
|
|
||||||
import localSettings from "../../../services/local-settings";
|
import localSettings from "../../../services/local-settings";
|
||||||
import SimpleView from "../../../components/layout/presets/simple-view";
|
import SimpleView from "../../../components/layout/presets/simple-view";
|
||||||
|
|
||||||
@ -118,6 +116,16 @@ export default function PostSettings() {
|
|||||||
client tags on events
|
client tags on events
|
||||||
</FormHelperText>
|
</FormHelperText>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
|
<FormControl>
|
||||||
|
<Flex alignItems="center">
|
||||||
|
<FormLabel htmlFor="mirrorBlobsOnShare" mb="0">
|
||||||
|
Always mirror media
|
||||||
|
</FormLabel>
|
||||||
|
<Switch id="mirrorBlobsOnShare" {...register("mirrorBlobsOnShare")} />
|
||||||
|
</Flex>
|
||||||
|
<FormHelperText>Copy all media to your personal blossom servers when sharing notes</FormHelperText>
|
||||||
|
</FormControl>
|
||||||
</SimpleView>
|
</SimpleView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user