diff --git a/src-gui/src/renderer/components/App.tsx b/src-gui/src/renderer/components/App.tsx
index 1d612f29..a911241c 100644
--- a/src-gui/src/renderer/components/App.tsx
+++ b/src-gui/src/renderer/components/App.tsx
@@ -9,6 +9,7 @@ import HistoryPage from "./pages/history/HistoryPage";
import SwapPage from "./pages/swap/SwapPage";
import WalletPage from "./pages/wallet/WalletPage";
import GlobalSnackbarProvider from "./snackbar/GlobalSnackbarProvider";
+import UpdaterDialog from "./modal/updater/UpdaterDialog";
const useStyles = makeStyles((theme) => ({
innerContent: {
@@ -58,6 +59,7 @@ export default function App() {
+
diff --git a/src-gui/src/renderer/components/modal/updater/UpdaterDialog.tsx b/src-gui/src/renderer/components/modal/updater/UpdaterDialog.tsx
new file mode 100644
index 00000000..58d6ffe1
--- /dev/null
+++ b/src-gui/src/renderer/components/modal/updater/UpdaterDialog.tsx
@@ -0,0 +1,166 @@
+import { useEffect, useState } from 'react';
+import {
+ Dialog,
+ DialogTitle,
+ DialogContent,
+ DialogContentText,
+ DialogActions,
+ Button,
+ LinearProgress,
+ Typography,
+ makeStyles,
+ LinearProgressProps,
+ Box,
+} from '@material-ui/core';
+import SystemUpdateIcon from '@material-ui/icons/SystemUpdate';
+import { check, Update, DownloadEvent } from '@tauri-apps/plugin-updater';
+import { useSnackbar } from 'notistack';
+import { relaunch } from '@tauri-apps/plugin-process';
+
+const useStyles = makeStyles((theme) => ({
+ progress: {
+ marginTop: theme.spacing(2)
+ },
+ releaseNotes: {
+ marginTop: theme.spacing(2),
+ marginBottom: theme.spacing(1)
+ },
+ noteContent: {
+ whiteSpace: 'pre-line'
+ }
+}));
+
+interface DownloadProgress {
+ contentLength: number | null;
+ downloadedBytes: number;
+}
+
+function LinearProgressWithLabel(props: LinearProgressProps & { label?: string }) {
+ return (
+
+
+
+
+
+
+ {props.label || `${Math.round(props.value)}%`}
+
+
+
+ );
+}
+
+export default function UpdaterDialog() {
+ const classes = useStyles();
+ const [availableUpdate, setAvailableUpdate] = useState(null);
+ const [downloadProgress, setDownloadProgress] = useState(null);
+ const {enqueueSnackbar} = useSnackbar();
+
+ useEffect(() => {
+ // Check for updates when component mounts
+ check().then((updateResponse) => {
+ setAvailableUpdate(updateResponse);
+ }).catch((err) => {
+ enqueueSnackbar(`Failed to check for updates: ${err}`, {
+ variant: 'error',
+ });
+ });
+ }, []);
+
+ // If no update is available, don't render the dialog
+ if (!availableUpdate?.available) return null;
+
+ function hideNotification() {
+ setAvailableUpdate(null);
+ };
+
+ async function handleInstall() {
+ try {
+ await availableUpdate.downloadAndInstall((event: DownloadEvent) => {
+ if (event.event === 'Started') {
+ setDownloadProgress({
+ contentLength: event.data.contentLength || null,
+ downloadedBytes: 0,
+ });
+ } else if (event.event === 'Progress') {
+ setDownloadProgress(prev => ({
+ ...prev,
+ downloadedBytes: prev.downloadedBytes + event.data.chunkLength,
+ }));
+ } else if (event.event === 'Finished') {
+ // Relaunch the application for the new version to be used
+ relaunch();
+ }
+ });
+ } catch (err) {
+ enqueueSnackbar(`Failed to install update: ${err}`, {
+ variant: "error"
+ });
+ }
+ };
+
+ const isDownloading = downloadProgress !== null;
+
+ const progress = isDownloading
+ ? Math.round((downloadProgress.downloadedBytes / downloadProgress.contentLength) * 100)
+ : 0;
+
+ return (
+
+ );
+}
diff --git a/src-gui/src/renderer/index.tsx b/src-gui/src/renderer/index.tsx
index bb2719e0..d0e9ff1b 100644
--- a/src-gui/src/renderer/index.tsx
+++ b/src-gui/src/renderer/index.tsx
@@ -18,8 +18,6 @@ import {
import App from "./components/App";
import { initEventListeners } from "./rpc";
import { persistor, store } from "./store/storeRenderer";
-import { Box } from "@material-ui/core";
-import { checkForAppUpdates } from "./updater";
const container = document.getElementById("root");
const root = createRoot(container!);
@@ -76,5 +74,4 @@ async function fetchInitialData() {
}
fetchInitialData();
-initEventListeners();
-checkForAppUpdates();
+initEventListeners();
\ No newline at end of file
diff --git a/src-gui/src/renderer/updater.ts b/src-gui/src/renderer/updater.ts
deleted file mode 100644
index 86a4a626..00000000
--- a/src-gui/src/renderer/updater.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { check } from "@tauri-apps/plugin-updater";
-import { ask, message } from "@tauri-apps/plugin-dialog";
-import { relaunch } from "@tauri-apps/plugin-process";
-
-export async function checkForAppUpdates() {
- const update = await check();
-
- if (update?.available) {
- const yes = await ask(
- `
-Update to ${update.version} is available!
-Release notes: ${update.body}
- `,
- {
- title: "Update Now!",
- kind: "info",
- okLabel: "Update",
- cancelLabel: "Cancel",
- }
- );
-
- if (yes) {
- await update.downloadAndInstall();
- await relaunch();
- }
- }
-}
\ No newline at end of file
diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json
index 24c7326d..b85d0b2e 100644
--- a/src-tauri/tauri.conf.json
+++ b/src-tauri/tauri.conf.json
@@ -41,7 +41,7 @@
"endpoints": [
"https://cdn.crabnebula.app/update/unstoppableswap/unstoppableswap-gui-rs/{{target}}-{{arch}}/{{current_version}}"
],
- "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEQyNTQ3NTQxQTQ2MkI4N0IKUldSN3VHS2tRWFZVMGpWYytkRFg4dFBzNEh5ZnlxaHBubGpRalVMMG5nVytiR3JPOUE3QjRxc00K"
+ "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEE2MDgxRDEwMDZENkYxNUMKUldSYzhkWUdFQjBJcGwzN24yZlduTzNndFZnVW9Qa1k2WFVTMEMxcHBSc2dSVVlzbVNHdGNFQ0EK"
},
"cli": {
"description": "Start the GUI application",