/* * Kyoo - A portable and vast media library solution. * Copyright (c) Kyoo. * * See AUTHORS.md and LICENSE file in the project root for full license information. * * Kyoo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * Kyoo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Kyoo. If not, see . */ import { usePortal } from "@gorhom/portal"; import { type ReactElement, createContext, useCallback, useContext, useRef } from "react"; import { View } from "react-native"; import { percent, px } from "yoshiki/native"; import { Button } from "./button"; import { imageBorderRadius } from "./constants"; import { P } from "./text"; import { SwitchVariant } from "./themes"; import { ts } from "./utils"; export type Snackbar = { key?: string; label: string; duration: number; actions?: Action[]; }; export type Action = { label: string; icon: ReactElement; action: () => void; }; const SnackbarContext = createContext<(snackbar: Snackbar) => void>(null!); export const SnackbarProvider = ({ children }: { children: ReactElement | ReactElement[] }) => { const { addPortal, removePortal } = usePortal(); const snackbars = useRef([]); const timeout = useRef(null); const createSnackbar = useCallback( (snackbar: Snackbar) => { if (snackbar.key) snackbars.current = snackbars.current.filter((x) => snackbar.key !== x.key); snackbars.current.unshift(snackbar); if (timeout.current) return; const updatePortal = () => { const top = snackbars.current.pop(); if (!top) { timeout.current = null; return; } const { key, ...props } = top; addPortal("snackbar", ); timeout.current = setTimeout(() => { removePortal("snackbar"); updatePortal(); }, snackbar.duration * 1000); }; updatePortal(); }, [addPortal, removePortal], ); return {children}; }; export const useSnackbar = () => { return useContext(SnackbarContext); }; const Snackbar = ({ label, actions }: Snackbar) => { // TODO: take navbar height into account for setting the position of the snacbar. return ( {({ css }) => ( theme.background, maxWidth: { sm: percent(75), md: percent(45), lg: px(500) }, margin: ts(1), padding: ts(1), flexDirection: "row", borderRadius: imageBorderRadius, })} >

{label}

{actions?.map((x, i) => (