tutu/src/platform/share.tsx
thislight 246771e8a0
All checks were successful
/ depoly (push) Successful in 1m19s
add alias ~platform and ~material
2024-11-22 17:24:58 +08:00

104 lines
2.4 KiB
TypeScript

import {
createEffect,
createSignal,
onCleanup,
type Component,
} from "solid-js";
import Scaffold from "~material/Scaffold";
import BottomSheet from "~material/BottomSheet";
import {
Button,
IconButton,
Input,
ThemeProvider,
Toolbar,
} from "@suid/material";
import { Close as CloseIcon, ContentCopy } from "@suid/icons-material";
import { Title } from "~material/typography";
import { render } from "solid-js/web";
import { useRootTheme } from "~material/theme";
const ShareBottomSheet: Component<{
data?: ShareData;
open?: boolean;
onClose: () => void;
}> = (props) => {
return (
<BottomSheet open={props.open} onClose={props.onClose} bottomUp>
<Scaffold
topbar={
<Toolbar>
<IconButton onClick={props.onClose}>
<CloseIcon />
</IconButton>
<Title>Share...</Title>
</Toolbar>
}
>
<div
style={{
"padding": "8px 8px calc(var(--safe-area-inset-bottom, 0px) + 40px)",
display: "flex",
}}
>
<Input
value={props.data?.url}
onChange={() => undefined}
fullWidth
/>
<Button
onClick={() => {
navigator.clipboard.writeText(props.data?.url ?? "");
}}
>
<ContentCopy sx={{ marginTop: "-.25em", marginRight: ".25em" }} />
Copy
</Button>
</div>
</Scaffold>
</BottomSheet>
);
};
export function canShare(data?: ShareData) {
if (navigator.canShare) {
return navigator.canShare(data);
}
return !!data?.url;
}
export async function share(data?: ShareData): Promise<void> {
if (navigator.share) {
return await navigator.share(data);
}
return new Promise((resolve) => {
const element = document.createElement("div");
document.body.appendChild(element);
const dispose = render(() => {
const [open, setOpen] = createSignal(true);
const theme = useRootTheme();
onCleanup(() => {
element.remove();
resolve();
});
createEffect(() => {
if (!open()) {
dispose();
}
});
return (
<ThemeProvider theme={theme()}>
<ShareBottomSheet
data={data}
open={open()}
onClose={() => setOpen(false)}
/>
</ThemeProvider>
);
}, element);
});
}