From 2c006c12f9cb1b82429bfc41a86d2993313a1b38 Mon Sep 17 00:00:00 2001 From: PhilReact Date: Wed, 5 Mar 2025 18:39:03 +0200 Subject: [PATCH] updated pwa --- index.html | 2 +- src/App.tsx | 8 +++++ src/background.ts | 44 ++++++++++++++++-------- src/components/InstallPWA.tsx | 64 +++++++++++++++++++++++++++++++++++ vite.config.ts | 10 ++++-- 5 files changed, 110 insertions(+), 18 deletions(-) create mode 100644 src/components/InstallPWA.tsx diff --git a/index.html b/index.html index 1c285cc..c543090 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - + Qortal Go diff --git a/src/App.tsx b/src/App.tsx index a1903b7..0f92b54 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -147,6 +147,7 @@ import { useBlockedAddresses } from "./components/Chat/useBlockUsers"; import { UserLookup } from "./components/UserLookup.tsx/UserLookup"; import { RegisterName } from "./components/RegisterName"; import { BuyQortInformation } from "./components/BuyQortInformation"; +import { InstallPWA } from "./components/InstallPWA"; type extStates = @@ -1839,6 +1840,13 @@ function App() { backgroundRepeat: desktopViewMode === "apps" && "no-repeat", }} > + +
+ +
+ { return parseInt(uid.rnd()) } -LocalNotifications.requestPermissions().then(permission => { - if (permission.display === 'granted') { - console.log("Notifications enabled"); - } -}).catch((error)=> console.error(error)); -FilePicker.requestPermissions().then(permission => { - if (permission?.publicStorage === 'granted') { - console.log("File access permission granted"); - } -}).catch((error)=> console.error(error));; +if(isNative){ + + LocalNotifications.requestPermissions().then(permission => { + if (permission.display === 'granted') { + console.log("Notifications enabled"); + } + }).catch((error)=> console.error(error)); + + FilePicker.requestPermissions().then(permission => { + if (permission?.publicStorage === 'granted') { + console.log("File access permission granted"); + } + }).catch((error)=> console.error(error)); +} + export let groupSecretkeys = {} @@ -435,7 +444,6 @@ export async function performPowTaskWeb(chatBytes, difficulty) { } export async function performPowTask(chatBytes, difficulty) { - const isNative = Capacitor.isNativePlatform(); const chatBytesArray = Uint8Array.from(Object.values(chatBytes)); const result = isNative ? await NativePOW.computeProofOfWork({ chatBytes, difficulty }) : await performPowTaskWeb(chatBytes, difficulty); return {nonce: result.nonce, chatBytesArray} @@ -3375,7 +3383,9 @@ export const checkThreads = async (bringBack) => { } }; -// Configure Background Fetch +if(isNative){ + + // Configure Background Fetch BackgroundFetch.configure({ minimumFetchInterval: 15, // Minimum 15-minute interval enableHeadless: true, // Enable headless mode for Android @@ -3400,7 +3410,9 @@ BackgroundFetch.configure({ BackgroundFetch.finish(taskId); }); +} +if(isNative){ LocalNotifications.addListener('localNotificationActionPerformed', async (event) => { @@ -3430,6 +3442,9 @@ LocalNotifications.addListener('localNotificationActionPerformed', async (event) } }); +} + + const initializeBackButton = () => { @@ -3443,5 +3458,6 @@ const initializeBackButton = () => { }; -// Call this function on app startup -initializeBackButton(); \ No newline at end of file +if(isNative){ + initializeBackButton(); +} diff --git a/src/components/InstallPWA.tsx b/src/components/InstallPWA.tsx new file mode 100644 index 0000000..012c952 --- /dev/null +++ b/src/components/InstallPWA.tsx @@ -0,0 +1,64 @@ +import { Button } from '@mui/material'; +import { useEffect, useState } from 'react'; + +export const InstallPWA = () => { + const [deferredPrompt, setDeferredPrompt] = useState(null); + const [showInstallButton, setShowInstallButton] = useState(false); + const [isStandalone, setIsStandalone] = useState(false); + + useEffect(() => { + // Check if app is already installed + if (window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone) { + setIsStandalone(true); + return; + } + + // Restore install prompt if previously stored + const wasPromptAvailable = localStorage.getItem("pwaPromptAvailable"); + if (wasPromptAvailable === "true") { + setShowInstallButton(true); + } + + // Listen for beforeinstallprompt event + const handleBeforeInstallPrompt = (e) => { + e.preventDefault(); // Prevent automatic prompt + setDeferredPrompt(e); + setShowInstallButton(true); + localStorage.setItem("pwaPromptAvailable", "true"); // Remember install prompt was available + }; + + window.addEventListener("beforeinstallprompt", handleBeforeInstallPrompt); + + return () => { + window.removeEventListener("beforeinstallprompt", handleBeforeInstallPrompt); + }; + }, []); + const handleInstallClick = () => { + if (deferredPrompt) { + deferredPrompt.prompt(); + deferredPrompt.userChoice.then((choiceResult) => { + if (choiceResult.outcome === "accepted") { + console.log("User accepted the install prompt"); + localStorage.removeItem("pwaPromptAvailable"); // Remove stored prompt + setShowInstallButton(false); + } else { + console.log("User dismissed the install prompt"); + setShowInstallButton(true); // Keep showing button + } + setDeferredPrompt(null); + }); + } + }; + + return ( +
+ {!isStandalone && showInstallButton && ( + + )} +
+ ); +}; \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index c5bcb0c..25e499a 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -12,15 +12,17 @@ export default defineConfig({ assetsInclude: ['**/*.wasm'], plugins: [react(), wasm(), topLevelAwait(), VitePWA({ - registerType: 'prompt', + registerType: "autoUpdate", + manifest: { name: 'Qortal Go', short_name: 'Go', description: 'Your easy access to the Qortal blockchain', start_url: '/', display: 'standalone', - theme_color: '#ffffff', - background_color: '#ffffff', + + theme_color: '#1f2023', + background_color: '#1f2023', icons: [ { src: '/qortal192.png', @@ -37,6 +39,8 @@ export default defineConfig({ workbox: { maximumFileSizeToCacheInBytes: 5 * 1024 * 1024, // 5MB limit disableDevLogs: true, // Suppresses logs in development + skipWaiting: true, // Forces the new version to activate immediately + clientsClaim: true // Makes the new service worker take control }, })], build: {