diff --git a/app/renderer/src/contexts/ConnnectorContext.tsx b/app/renderer/src/contexts/ConnnectorContext.tsx index a270218e..b84666c4 100644 --- a/app/renderer/src/contexts/ConnnectorContext.tsx +++ b/app/renderer/src/contexts/ConnnectorContext.tsx @@ -5,9 +5,14 @@ import { ElectronInvokeConnector, } from "./connectors/ElectronConnector"; import { - TauriConnectorProvider, - TauriInvokeConnector, -} from "./connectors/TauriConnector"; + TauriDesktopConnectorProvider, + TauriDesktopInvokeConnector, +} from "./connectors/TauriDesktopConnector"; +import { detectOS } from "../utils"; +import { + TauriMobileConnectorProvider, + TauriMobileInvokeConnector, +} from "./connectors/TauriMobileConnector"; export type ConnectorProps = { onMinimizeCallback?: () => void; @@ -23,7 +28,10 @@ export function getInvokeConnector() { if (isElectron()) { return ElectronInvokeConnector; } else if (window.__TAURI__) { - return TauriInvokeConnector; + let os = detectOS(); + if (os === "iOS" || os === "Android") + return TauriMobileInvokeConnector; + return TauriDesktopInvokeConnector; } return undefined; } @@ -33,7 +41,12 @@ export const ConnectorProvider: React.FC = ({ children }) => { if (isElectron()) { Connector = ElectronConnectorProvider; } else if (window.__TAURI__) { - Connector = TauriConnectorProvider; + let os = detectOS(); + if (os === "iOS" || os === "Android") { + Connector = TauriMobileConnectorProvider; + } else { + Connector = TauriDesktopConnectorProvider; + } } return ; diff --git a/app/renderer/src/contexts/connectors/TauriConnector.tsx b/app/renderer/src/contexts/connectors/TauriDesktopConnector.tsx similarity index 95% rename from app/renderer/src/contexts/connectors/TauriConnector.tsx rename to app/renderer/src/contexts/connectors/TauriDesktopConnector.tsx index 5328b208..f6d62bd6 100644 --- a/app/renderer/src/contexts/connectors/TauriConnector.tsx +++ b/app/renderer/src/contexts/connectors/TauriDesktopConnector.tsx @@ -24,7 +24,7 @@ import { listen } from "@tauri-apps/api/event"; import { open } from "@tauri-apps/plugin-shell"; import { setUpdateBody, setUpdateVersion } from "../../store/update"; -export const TauriInvokeConnector = { +export const TauriDesktopInvokeConnector = { send: (event: string, ...payload: any) => { invoke(event.toLowerCase(), ...payload).catch((err) => console.error(err) @@ -32,7 +32,9 @@ export const TauriInvokeConnector = { }, }; -export const TauriConnectorProvider: React.FC = ({ children }) => { +export const TauriDesktopConnectorProvider: React.FC = ({ + children, +}) => { const dispatch = useDispatch(); const settings: SettingTypes = useSelector( @@ -100,8 +102,9 @@ export const TauriConnectorProvider: React.FC = ({ children }) => { const timer = useSelector((state: AppStateTypes) => state.timer); - const { count, duration, timerType, shouldFullscreen } = - useContext(CounterContext); + const { count, duration, timerType, shouldFullscreen } = useContext( + CounterContext + ); const dashOffset = (duration - count) * (24 / duration); const onMinimizeCallback = useCallback(() => { @@ -174,7 +177,7 @@ export const TauriConnectorProvider: React.FC = ({ children }) => { const img = new Image(); img.src = svgXML; - img.onload = function () { + img.onload = function() { ctx?.drawImage(img, 0, 0); const dataUrl = canvas.toDataURL("image/png"); diff --git a/app/renderer/src/contexts/connectors/TauriMobileConnector.tsx b/app/renderer/src/contexts/connectors/TauriMobileConnector.tsx new file mode 100644 index 00000000..3093747c --- /dev/null +++ b/app/renderer/src/contexts/connectors/TauriMobileConnector.tsx @@ -0,0 +1,113 @@ +import React, { useCallback, useContext, useEffect } from "react"; +import { ConnnectorContext } from "../ConnnectorContext"; +import { useDispatch, useSelector } from "react-redux"; +import { AppStateTypes, SettingTypes } from "../../store"; +import { CounterContext } from "../CounterContext"; +import { + CHECK_FOR_UPDATES, + SET_ALWAYS_ON_TOP, + SET_CLOSE, + SET_COMPACT_MODE, + SET_FULLSCREEN_BREAK, + SET_MINIMIZE, + SET_NATIVE_TITLEBAR, + SET_SHOW, + SET_UI_THEME, + TRAY_ICON_UPDATE, + UPDATE_AVAILABLE, +} from "@pomatez/shareables"; +import { encodeSvg } from "../../utils"; +import { TraySVG } from "../../components"; +import { enable, disable } from "@tauri-apps/plugin-autostart"; +import { invoke } from "@tauri-apps/api/primitives"; +import { listen } from "@tauri-apps/api/event"; +import { open } from "@tauri-apps/plugin-shell"; +import { setUpdateBody, setUpdateVersion } from "../../store/update"; + +export const TauriMobileInvokeConnector = { + send: (event: string, ...payload: any) => { + invoke(event.toLowerCase(), ...payload).catch((err) => + console.error(err) + ); + }, +}; + +export const TauriMobileConnectorProvider: React.FC = ({ + children, +}) => { + const dispatch = useDispatch(); + + /** + * Need to test keyboard input on mobile before removing this. + */ + useEffect(() => { + function handleKeyDown(event: KeyboardEvent) { + if ( + (event.ctrlKey && (event.key === "r" || event.key === "R")) || + event.key === "F5" + ) { + event.preventDefault(); + } + } + + window.addEventListener("keydown", handleKeyDown); + return () => { + window.removeEventListener("keydown", handleKeyDown); + }; + }, []); + + /** + * Apparently you can just use _blank as the target though it definitely isn't working on windows. + * + * This is a workaround :) + */ + useEffect(() => { + function urlClickHandler(e: MouseEvent) { + const target = e.target as HTMLAnchorElement; + if ( + target && + target.tagName === "A" && + target.href.startsWith("http") && + target.target === "_blank" + ) { + e.preventDefault(); + open(target.href); // Use Tauri's shell module to open external links + } + } + window.addEventListener("click", urlClickHandler); + return () => { + window.removeEventListener("click", urlClickHandler); + }; + }, []); + + /** + * Not needed as tauri already opens these externally. + */ + const openExternalCallback = useCallback(() => {}, []); + + useEffect(() => { + const unlisten = listen<{ body: string; version: string }>( + UPDATE_AVAILABLE, + (updateInfo) => { + console.log("Update Info", updateInfo.payload); + dispatch(setUpdateVersion(updateInfo?.payload?.version)); + dispatch(setUpdateBody(updateInfo?.payload?.body)); + } + ); + return () => { + unlisten.then((f) => f()); + }; + }, [dispatch]); + + return ( + {}, + onExitCallback: () => {}, + openExternalCallback, + }} + > + {children} + + ); +}; diff --git a/app/renderer/src/utils/detectOS.ts b/app/renderer/src/utils/detectOS.ts index bc3081f9..1cc503fb 100644 --- a/app/renderer/src/utils/detectOS.ts +++ b/app/renderer/src/utils/detectOS.ts @@ -1,8 +1,10 @@ -export type OSTypes = "Windows" | "MacOS" | "Linux"; +export type OSTypes = "Android" | "iOS" | "Windows" | "MacOS" | "Linux"; export function detectOS(): OSTypes { const { appVersion } = navigator; + if (appVersion.indexOf("Android") !== -1) return "Android"; + if (appVersion.indexOf("iOS") !== -1) return "iOS"; if (appVersion.indexOf("Win") !== -1) return "Windows"; if (appVersion.indexOf("Mac") !== -1) return "MacOS"; if (appVersion.indexOf("Linux") !== -1) return "Linux";