/ components / UpdateBanner.tsx
UpdateBanner.tsx
 1  import { useState, useEffect } from 'react';
 2  import { X } from 'lucide-react';
 3  import type { UpdateInfo } from '../lib/types';
 4  
 5  const supportsAutoUpdate = window.electronAPI.platform !== 'linux' && window.electronAPI.isPackaged;
 6  
 7  export function UpdateBanner() {
 8    const [update, setUpdate] = useState<UpdateInfo | null>(null);
 9    const [readyVersion, setReadyVersion] = useState<string | null>(null);
10  
11    useEffect(() => {
12      window.electronAPI.onUpdateAvailable((info) => setUpdate(info));
13      window.electronAPI.onUpdateReady((version) => setReadyVersion(version));
14      return () => {
15        window.electronAPI.offUpdateAvailable();
16        window.electronAPI.offUpdateReady();
17      };
18    }, []);
19  
20    // macOS/Windows: show banner when update has been downloaded and is ready to install
21    if (supportsAutoUpdate && readyVersion !== null) {
22      return (
23        <div className="updateBanner flex items-center justify-between gap-3 px-6 py-1.5 text-xs">
24          <span>
25            Gnosis <strong className="font-semibold">v{readyVersion}</strong> will install on next restart
26          </span>
27          <button onClick={() => setReadyVersion(null)} className="shrink-0 transition-opacity hover:opacity-80" aria-label="Dismiss">
28            <X className="h-3 w-3" />
29          </button>
30        </div>
31      );
32    }
33  
34    // Linux: show banner when a new version is available for manual download
35    if (!update || supportsAutoUpdate) return null;
36  
37    const { version, releaseUrl } = update;
38  
39    function handleDismiss() {
40      void window.electronAPI.dismissUpdate(version);
41      setUpdate(null);
42    }
43  
44    return (
45      <div className="updateBanner flex items-center justify-between gap-3 px-6 py-1.5 text-xs">
46        <div className="flex items-center gap-3">
47          <span>
48            Gnosis <strong className="font-semibold">v{version}</strong> is available
49          </span>
50          <button
51            onClick={() => void window.electronAPI.openExternal(releaseUrl)}
52            className="updateBanner-btn px-2 py-0.5 rounded-sm text-xs transition-colors"
53          >
54            Download
55          </button>
56        </div>
57        <button onClick={handleDismiss} className="shrink-0 transition-opacity hover:opacity-80" aria-label="Dismiss">
58          <X className="h-3 w-3" />
59        </button>
60      </div>
61    );
62  }