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: {