kubeops 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/electron/main.js CHANGED
@@ -106,14 +106,43 @@ function setupAutoUpdater() {
106
106
  });
107
107
  }
108
108
 
109
+ function setupDevUpdaterIPC() {
110
+ ipcMain.handle('updater:check', async () => {
111
+ sendUpdateStatus({ status: 'not-available', version: app.getVersion() });
112
+ return null;
113
+ });
114
+
115
+ ipcMain.handle('updater:download', async () => {
116
+ sendUpdateStatus({ status: 'error', message: 'Updates are not available in development mode' });
117
+ });
118
+
119
+ ipcMain.handle('updater:install', () => {});
120
+
121
+ ipcMain.handle('updater:get-version', () => {
122
+ return app.getVersion();
123
+ });
124
+ }
125
+
109
126
  function setupUpdaterIPC() {
110
127
  ipcMain.handle('updater:check', async () => {
111
- const result = await autoUpdater.checkForUpdates();
112
- return result?.updateInfo;
128
+ try {
129
+ const result = await autoUpdater.checkForUpdates();
130
+ return result?.updateInfo;
131
+ } catch (err) {
132
+ writeErrorLog('updater:check', err);
133
+ sendUpdateStatus({ status: 'error', message: err.message || 'Update check failed' });
134
+ throw err;
135
+ }
113
136
  });
114
137
 
115
138
  ipcMain.handle('updater:download', async () => {
116
- await autoUpdater.downloadUpdate();
139
+ try {
140
+ await autoUpdater.downloadUpdate();
141
+ } catch (err) {
142
+ writeErrorLog('updater:download', err);
143
+ sendUpdateStatus({ status: 'error', message: err.message || 'Download failed' });
144
+ throw err;
145
+ }
117
146
  });
118
147
 
119
148
  ipcMain.handle('updater:install', () => {
@@ -398,7 +427,7 @@ app.whenReady().then(async () => {
398
427
  }
399
428
  createWindow();
400
429
 
401
- // Auto-update setup (production only)
430
+ // Auto-update setup
402
431
  if (!isDev) {
403
432
  setupAutoUpdater();
404
433
  setupUpdaterIPC();
@@ -407,6 +436,9 @@ app.whenReady().then(async () => {
407
436
  writeErrorLog('updater:auto-check', err);
408
437
  });
409
438
  }, 5000);
439
+ } else {
440
+ // Dev mode: register IPC handlers that respond with dev-friendly messages
441
+ setupDevUpdaterIPC();
410
442
  }
411
443
  } catch (err) {
412
444
  writeErrorLog('main:startup', err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kubeops",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "A modern desktop client for Kubernetes cluster management",
5
5
  "main": "electron/main.js",
6
6
  "repository": {
@@ -12,6 +12,7 @@ import { Button } from '@/components/ui/button';
12
12
  import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
13
13
  import { Server, ArrowRight, Search, Settings, RefreshCw, LogIn, Loader2, CircleCheck } from 'lucide-react';
14
14
  import { ThemeToggle } from '@/components/layout/theme-toggle';
15
+ import { UpdateIndicator } from '@/components/layout/header';
15
16
  import { SettingsDialog } from '@/components/settings/settings-dialog';
16
17
  import { toast } from 'sonner';
17
18
 
@@ -174,6 +175,7 @@ export default function ClustersPage() {
174
175
  >
175
176
  <RefreshCw className={`h-4 w-4 ${refreshing ? 'animate-spin' : ''}`} />
176
177
  </Button>
178
+ <UpdateIndicator />
177
179
  <Button
178
180
  variant="ghost"
179
181
  size="icon"
@@ -15,7 +15,7 @@ import {
15
15
  TooltipTrigger,
16
16
  } from '@/components/ui/tooltip';
17
17
 
18
- function UpdateIndicator() {
18
+ export function UpdateIndicator() {
19
19
  const {
20
20
  phase, version, percent, errorMessage, isAvailable,
21
21
  checkForUpdates, downloadUpdate, quitAndInstall,
@@ -28,6 +28,7 @@ export function useAutoUpdate() {
28
28
  apiRef.current?.getAppVersion().then(setAppVersion).catch(() => {});
29
29
  }, []);
30
30
 
31
+ // Event listener for push-based status updates (download progress, auto-check at startup)
31
32
  useEffect(() => {
32
33
  if (!apiRef.current) return;
33
34
 
@@ -62,17 +63,46 @@ export function useAutoUpdate() {
62
63
  return unsubscribe;
63
64
  }, []);
64
65
 
66
+ // checkForUpdates uses IPC return value as primary, event listener as fallback
65
67
  const checkForUpdates = useCallback(() => {
66
68
  if (!apiRef.current) return;
67
69
  setPhase('checking');
68
70
  setErrorMessage(null);
69
- apiRef.current.checkForUpdates().catch(() => {});
71
+ apiRef.current.checkForUpdates()
72
+ .then((info: any) => {
73
+ if (!info) {
74
+ // No update info returned — treat as up-to-date
75
+ setPhase((prev) => {
76
+ if (prev === 'checking') {
77
+ setTimeout(() => setPhase('idle'), 3000);
78
+ return 'not-available';
79
+ }
80
+ return prev;
81
+ });
82
+ return;
83
+ }
84
+ // IPC returned updateInfo — update is available
85
+ setPhase((prev) => {
86
+ // Only update if event listener hasn't already handled it
87
+ if (prev === 'checking') return 'available';
88
+ return prev;
89
+ });
90
+ if (info.version) setVersion(info.version);
91
+ })
92
+ .catch((err: any) => {
93
+ setPhase('error');
94
+ setErrorMessage(err?.message || 'Update check failed');
95
+ });
70
96
  }, []);
71
97
 
72
98
  const downloadUpdate = useCallback(() => {
73
99
  if (!apiRef.current) return;
74
100
  setPercent(0);
75
- apiRef.current.downloadUpdate().catch(() => {});
101
+ setPhase('downloading');
102
+ apiRef.current.downloadUpdate().catch((err: any) => {
103
+ setPhase('error');
104
+ setErrorMessage(err?.message || 'Download failed');
105
+ });
76
106
  }, []);
77
107
 
78
108
  const quitAndInstall = useCallback(() => {