Stijnus commited on
Commit
ee67bf1
·
1 Parent(s): c200e2f

Update UpdateTab.tsx

Browse files
app/components/@settings/tabs/update/UpdateTab.tsx CHANGED
@@ -4,6 +4,7 @@ import { useSettings } from '~/lib/hooks/useSettings';
4
  import { logStore } from '~/lib/stores/logs';
5
  import { toast } from 'react-toastify';
6
  import { Dialog, DialogRoot, DialogTitle, DialogDescription, DialogButton } from '~/components/ui/Dialog';
 
7
 
8
  interface UpdateProgress {
9
  stage: 'fetch' | 'pull' | 'install' | 'build' | 'complete';
@@ -80,7 +81,7 @@ const UpdateTab = () => {
80
  const { isLatestBranch } = useSettings();
81
  const [isChecking, setIsChecking] = useState(false);
82
  const [error, setError] = useState<string | null>(null);
83
- const [updateSettings] = useState<UpdateSettings>(() => {
84
  const stored = localStorage.getItem('update_settings');
85
  return stored
86
  ? JSON.parse(stored)
@@ -176,36 +177,154 @@ const UpdateTab = () => {
176
  };
177
 
178
  return (
179
- <div className="space-y-4 p-4">
180
- <div className="flex items-center justify-between">
181
- <h2 className="text-xl font-semibold">Updates</h2>
182
- <button
183
- onClick={() => {
184
- setError(null);
185
- checkForUpdates();
186
- }}
187
- className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors disabled:opacity-50"
188
- disabled={isChecking}
189
- >
190
- {isChecking ? (
191
- <div className="flex items-center">
192
- <motion.div
193
- animate={{ rotate: 360 }}
194
- transition={{ duration: 1, repeat: Infinity, ease: 'linear' }}
195
- className="w-4 h-4 border-2 border-white border-t-transparent rounded-full mr-2"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  />
197
- Checking...
 
 
 
 
 
 
198
  </div>
199
- ) : (
200
- 'Check for Updates'
201
- )}
202
- </button>
203
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
- {/* Show progress information */}
206
- {updateProgress && <UpdateProgressDisplay progress={updateProgress} />}
207
 
208
- {error && <div className="mt-4 p-4 bg-red-100 text-red-700 rounded">{error}</div>}
 
209
 
210
  {/* Update dialog */}
211
  <DialogRoot open={showUpdateDialog} onOpenChange={setShowUpdateDialog}>
 
4
  import { logStore } from '~/lib/stores/logs';
5
  import { toast } from 'react-toastify';
6
  import { Dialog, DialogRoot, DialogTitle, DialogDescription, DialogButton } from '~/components/ui/Dialog';
7
+ import { classNames } from '~/utils/classNames';
8
 
9
  interface UpdateProgress {
10
  stage: 'fetch' | 'pull' | 'install' | 'build' | 'complete';
 
81
  const { isLatestBranch } = useSettings();
82
  const [isChecking, setIsChecking] = useState(false);
83
  const [error, setError] = useState<string | null>(null);
84
+ const [updateSettings, setUpdateSettings] = useState<UpdateSettings>(() => {
85
  const stored = localStorage.getItem('update_settings');
86
  return stored
87
  ? JSON.parse(stored)
 
177
  };
178
 
179
  return (
180
+ <div className="flex flex-col gap-6">
181
+ <motion.div
182
+ className="flex items-center gap-3"
183
+ initial={{ opacity: 0, y: -20 }}
184
+ animate={{ opacity: 1, y: 0 }}
185
+ transition={{ duration: 0.3 }}
186
+ >
187
+ <div className="i-ph:arrow-circle-up text-xl text-purple-500" />
188
+ <div>
189
+ <h3 className="text-lg font-medium text-bolt-elements-textPrimary">Updates</h3>
190
+ <p className="text-sm text-bolt-elements-textSecondary">Check for and manage application updates</p>
191
+ </div>
192
+ </motion.div>
193
+
194
+ {/* Update Settings Card */}
195
+ <motion.div
196
+ className="p-6 rounded-xl bg-white dark:bg-[#0A0A0A] border border-[#E5E5E5] dark:border-[#1A1A1A]"
197
+ initial={{ opacity: 0, y: 20 }}
198
+ animate={{ opacity: 1, y: 0 }}
199
+ transition={{ duration: 0.3, delay: 0.1 }}
200
+ >
201
+ <div className="flex items-center gap-3 mb-6">
202
+ <div className="i-ph:gear text-purple-500 w-5 h-5" />
203
+ <h3 className="text-lg font-medium text-bolt-elements-textPrimary">Update Settings</h3>
204
+ </div>
205
+
206
+ <div className="space-y-4">
207
+ <div className="flex items-center justify-between">
208
+ <div>
209
+ <span className="text-sm text-bolt-elements-textPrimary">Automatic Updates</span>
210
+ <p className="text-xs text-bolt-elements-textSecondary">
211
+ Automatically check and apply updates when available
212
+ </p>
213
+ </div>
214
+ <button
215
+ onClick={() => setUpdateSettings((prev) => ({ ...prev, autoUpdate: !prev.autoUpdate }))}
216
+ className={classNames(
217
+ 'relative inline-flex h-6 w-11 items-center rounded-full transition-colors',
218
+ updateSettings.autoUpdate ? 'bg-purple-500' : 'bg-gray-200 dark:bg-gray-700',
219
+ )}
220
+ >
221
+ <span
222
+ className={classNames(
223
+ 'inline-block h-4 w-4 transform rounded-full bg-white transition-transform',
224
+ updateSettings.autoUpdate ? 'translate-x-6' : 'translate-x-1',
225
+ )}
226
  />
227
+ </button>
228
+ </div>
229
+
230
+ <div className="flex items-center justify-between">
231
+ <div>
232
+ <span className="text-sm text-bolt-elements-textPrimary">In-App Notifications</span>
233
+ <p className="text-xs text-bolt-elements-textSecondary">Show notifications when updates are available</p>
234
  </div>
235
+ <button
236
+ onClick={() => setUpdateSettings((prev) => ({ ...prev, notifyInApp: !prev.notifyInApp }))}
237
+ className={classNames(
238
+ 'relative inline-flex h-6 w-11 items-center rounded-full transition-colors',
239
+ updateSettings.notifyInApp ? 'bg-purple-500' : 'bg-gray-200 dark:bg-gray-700',
240
+ )}
241
+ >
242
+ <span
243
+ className={classNames(
244
+ 'inline-block h-4 w-4 transform rounded-full bg-white transition-transform',
245
+ updateSettings.notifyInApp ? 'translate-x-6' : 'translate-x-1',
246
+ )}
247
+ />
248
+ </button>
249
+ </div>
250
+
251
+ <div className="flex items-center justify-between">
252
+ <div>
253
+ <span className="text-sm text-bolt-elements-textPrimary">Check Interval</span>
254
+ <p className="text-xs text-bolt-elements-textSecondary">How often to check for updates</p>
255
+ </div>
256
+ <select
257
+ value={updateSettings.checkInterval}
258
+ onChange={(e) => setUpdateSettings((prev) => ({ ...prev, checkInterval: Number(e.target.value) }))}
259
+ className={classNames(
260
+ 'px-3 py-2 rounded-lg text-sm',
261
+ 'bg-[#F5F5F5] dark:bg-[#1A1A1A]',
262
+ 'border border-[#E5E5E5] dark:border-[#1A1A1A]',
263
+ 'text-bolt-elements-textPrimary',
264
+ 'hover:bg-[#E5E5E5] dark:hover:bg-[#2A2A2A]',
265
+ 'transition-colors duration-200',
266
+ )}
267
+ >
268
+ <option value="6">6 hours</option>
269
+ <option value="12">12 hours</option>
270
+ <option value="24">24 hours</option>
271
+ <option value="48">48 hours</option>
272
+ </select>
273
+ </div>
274
+ </div>
275
+ </motion.div>
276
+
277
+ {/* Update Status Card */}
278
+ <motion.div
279
+ className="p-6 rounded-xl bg-white dark:bg-[#0A0A0A] border border-[#E5E5E5] dark:border-[#1A1A1A]"
280
+ initial={{ opacity: 0, y: 20 }}
281
+ animate={{ opacity: 1, y: 0 }}
282
+ transition={{ duration: 0.3, delay: 0.2 }}
283
+ >
284
+ <div className="flex items-center justify-between mb-6">
285
+ <div className="flex items-center gap-3">
286
+ <div className="i-ph:arrows-clockwise text-purple-500 w-5 h-5" />
287
+ <h3 className="text-lg font-medium text-bolt-elements-textPrimary">Update Status</h3>
288
+ </div>
289
+ <button
290
+ onClick={() => {
291
+ setError(null);
292
+ checkForUpdates();
293
+ }}
294
+ className={classNames(
295
+ 'flex items-center gap-2 px-4 py-2 rounded-lg text-sm',
296
+ 'bg-[#F5F5F5] dark:bg-[#1A1A1A]',
297
+ 'hover:bg-purple-500/10 hover:text-purple-500',
298
+ 'dark:hover:bg-purple-500/20 dark:hover:text-purple-500',
299
+ 'text-bolt-elements-textPrimary',
300
+ 'transition-colors duration-200',
301
+ 'disabled:opacity-50 disabled:cursor-not-allowed',
302
+ )}
303
+ disabled={isChecking}
304
+ >
305
+ {isChecking ? (
306
+ <div className="flex items-center gap-2">
307
+ <motion.div
308
+ animate={{ rotate: 360 }}
309
+ transition={{ duration: 1, repeat: Infinity, ease: 'linear' }}
310
+ className="i-ph:arrows-clockwise w-4 h-4"
311
+ />
312
+ Checking...
313
+ </div>
314
+ ) : (
315
+ <>
316
+ <div className="i-ph:arrows-clockwise w-4 h-4" />
317
+ Check for Updates
318
+ </>
319
+ )}
320
+ </button>
321
+ </div>
322
 
323
+ {/* Show progress information */}
324
+ {updateProgress && <UpdateProgressDisplay progress={updateProgress} />}
325
 
326
+ {error && <div className="mt-4 p-4 bg-red-100 text-red-700 rounded">{error}</div>}
327
+ </motion.div>
328
 
329
  {/* Update dialog */}
330
  <DialogRoot open={showUpdateDialog} onOpenChange={setShowUpdateDialog}>