TootActionGroup: added share button (closes #18)
This commit is contained in:
		
							parent
							
								
									6506a60022
								
							
						
					
					
						commit
						161c72fea5
					
				
					 3 changed files with 129 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -1,13 +1,15 @@
 | 
			
		|||
//! This module has side effect.
 | 
			
		||||
//! It recommended to include the module by <script> tag.
 | 
			
		||||
if (!document.body.animate) {
 | 
			
		||||
if (typeof document.body.animate === "undefined") {
 | 
			
		||||
  // @ts-ignore: this file is polyfill, no exposed decls
 | 
			
		||||
  import("web-animations-js").then(() => { // all target platforms supported, prepared to remove
 | 
			
		||||
  import("web-animations-js").then(() => {
 | 
			
		||||
    // all target platforms supported, prepared to remove
 | 
			
		||||
    console.warn("web animation polyfill is included");
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (!window.crypto.randomUUID) { // Chrome/Edge 92+
 | 
			
		||||
if (typeof window.crypto.randomUUID === "undefined") {
 | 
			
		||||
  // Chrome/Edge 92+
 | 
			
		||||
  // https://stackoverflow.com/a/2117523/2800218
 | 
			
		||||
  // LICENSE: https://creativecommons.org/licenses/by-sa/4.0/legalcode
 | 
			
		||||
  window.crypto.randomUUID =
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										104
									
								
								src/platform/share.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								src/platform/share.tsx
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,104 @@
 | 
			
		|||
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/mui";
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue