104 lines
2.4 KiB
TypeScript
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);
|
|
});
|
|
}
|