fix: remind me later updater (#5191)

* fix: remind me later app updater

* chore: update state app updater

* chore sync state
This commit is contained in:
Faisal Amir 2025-06-04 15:35:38 +07:00 committed by GitHub
parent 6faca3e732
commit da10502bdd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 141 additions and 62 deletions

View File

@ -6,7 +6,7 @@ import { Button } from '@/components/ui/button'
import { useState, useEffect } from 'react'
import { useReleaseNotes } from '@/hooks/useReleaseNotes'
import { RenderMarkdown } from '../RenderMarkdown'
import { isDev } from '@/lib/utils'
import { cn, isDev } from '@/lib/utils'
const DialogAppUpdater = () => {
const {
@ -38,12 +38,31 @@ const DialogAppUpdater = () => {
checkForUpdate()
}, [checkForUpdate])
if (updateState.remindMeLater) return null
const [appUpdateState, setAppUpdateState] = useState({
remindMeLater: false,
isUpdateAvailable: false,
})
useEffect(() => {
setAppUpdateState({
remindMeLater: updateState.remindMeLater,
isUpdateAvailable: updateState.isUpdateAvailable,
})
}, [updateState])
if (appUpdateState.remindMeLater) return null
console.log(appUpdateState)
console.log(updateState)
return (
<>
{updateState.isUpdateAvailable && (
<div className="fixed z-50 w-[400px] bottom-3 right-3 bg-main-view text-main-view-fg flex items-center justify-center border border-main-view-fg/10 rounded-lg shadow-md">
{appUpdateState.isUpdateAvailable && (
<div
className={cn(
'fixed z-50 w-[400px] bottom-3 right-3 bg-main-view text-main-view-fg flex items-center justify-center border border-main-view-fg/10 rounded-lg shadow-md'
)}
>
<div className="px-0 py-4">
<div className="px-4">
<div className="flex items-start gap-2">

View File

@ -1,6 +1,6 @@
import { isDev } from '@/lib/utils'
import { check, Update } from '@tauri-apps/plugin-updater'
import { useState, useCallback } from 'react'
import { useState, useCallback, useEffect } from 'react'
import { events, AppEvent } from '@janhq/core'
export interface UpdateState {
@ -24,64 +24,125 @@ export const useAppUpdater = () => {
remindMeLater: false,
})
const checkForUpdate = useCallback(async (resetRemindMeLater = false) => {
try {
// Reset remindMeLater if requested (e.g., when called from settings)
if (resetRemindMeLater) {
setUpdateState((prev) => ({
...prev,
remindMeLater: false,
}))
}
if (!isDev()) {
// Production mode - use actual Tauri updater
const update = await check()
if (update) {
setUpdateState((prev) => ({
...prev,
isUpdateAvailable: true,
updateInfo: update,
}))
console.log('Update available:', update.version)
return update
} else {
// No update available - reset state
setUpdateState((prev) => ({
...prev,
isUpdateAvailable: false,
updateInfo: null,
}))
return null
}
} else {
setUpdateState((prev) => ({
...prev,
isUpdateAvailable: false,
updateInfo: null,
}))
return null
}
} catch (error) {
console.error('Error checking for updates:', error)
// Reset state on error
// Listen for app update state sync events
useEffect(() => {
const handleUpdateStateSync = (newState: Partial<UpdateState>) => {
setUpdateState((prev) => ({
...prev,
isUpdateAvailable: false,
updateInfo: null,
...newState,
}))
return null
}
events.on('onAppUpdateStateSync', handleUpdateStateSync)
return () => {
events.off('onAppUpdateStateSync', handleUpdateStateSync)
}
}, [])
const setRemindMeLater = useCallback((remind: boolean) => {
setUpdateState((prev) => ({
...prev,
remindMeLater: remind,
}))
}, [])
const syncStateToOtherInstances = useCallback(
(partialState: Partial<UpdateState>) => {
// Emit event to sync state across all useAppUpdater instances
events.emit('onAppUpdateStateSync', partialState)
},
[]
)
const checkForUpdate = useCallback(
async (resetRemindMeLater = false) => {
try {
// Reset remindMeLater if requested (e.g., when called from settings)
if (resetRemindMeLater) {
const newState = {
remindMeLater: false,
}
setUpdateState((prev) => ({
...prev,
...newState,
}))
// Sync to other instances
syncStateToOtherInstances(newState)
}
if (!isDev()) {
// Production mode - use actual Tauri updater
const update = await check()
if (update) {
const newState = {
isUpdateAvailable: true,
remindMeLater: false,
updateInfo: update,
}
setUpdateState((prev) => ({
...prev,
...newState,
}))
// Sync to other instances
syncStateToOtherInstances(newState)
console.log('Update available:', update.version)
return update
} else {
// No update available - reset state
const newState = {
isUpdateAvailable: false,
updateInfo: null,
}
setUpdateState((prev) => ({
...prev,
...newState,
}))
// Sync to other instances
syncStateToOtherInstances(newState)
return null
}
} else {
const newState = {
isUpdateAvailable: false,
updateInfo: null,
...(resetRemindMeLater && { remindMeLater: false }),
}
setUpdateState((prev) => ({
...prev,
...newState,
}))
// Sync to other instances
syncStateToOtherInstances(newState)
return null
}
} catch (error) {
console.error('Error checking for updates:', error)
// Reset state on error
const newState = {
isUpdateAvailable: false,
updateInfo: null,
}
setUpdateState((prev) => ({
...prev,
...newState,
}))
// Sync to other instances
syncStateToOtherInstances(newState)
return null
}
},
[syncStateToOtherInstances]
)
const setRemindMeLater = useCallback(
(remind: boolean) => {
const newState = {
remindMeLater: remind,
}
setUpdateState((prev) => ({
...prev,
...newState,
}))
// Sync to other instances
syncStateToOtherInstances(newState)
},
[syncStateToOtherInstances]
)
const downloadAndInstallUpdate = useCallback(async () => {
if (!updateState.updateInfo) return

View File

@ -9,7 +9,7 @@ import LanguageSwitcher from '@/containers/LanguageSwitcher'
import { useTranslation } from 'react-i18next'
import { useGeneralSetting } from '@/hooks/useGeneralSetting'
import { useAppUpdater } from '@/hooks/useAppUpdater'
import { useEffect, useState } from 'react'
import { useEffect, useState, useCallback } from 'react'
import { open } from '@tauri-apps/plugin-dialog'
import { revealItemInDir } from '@tauri-apps/plugin-opener'
import ChangeDataFolderLocation from '@/containers/dialogs/ChangeDataFolderLocation'
@ -63,7 +63,7 @@ const openFileTitle = (): string => {
function General() {
const { t } = useTranslation()
const { spellCheckChatInput, setSpellCheckChatInput } = useGeneralSetting()
const { checkForUpdate, setRemindMeLater } = useAppUpdater()
const { checkForUpdate } = useAppUpdater()
const [janDataFolder, setJanDataFolder] = useState<string | undefined>()
const [isCopied, setIsCopied] = useState(false)
const [selectedNewPath, setSelectedNewPath] = useState<string | null>(null)
@ -179,9 +179,8 @@ function General() {
}
}
const handleCheckForUpdate = async () => {
const handleCheckForUpdate = useCallback(async () => {
setIsCheckingUpdate(true)
setRemindMeLater(false)
try {
if (isDev())
return toast.info('You are running a development version of Jan!')
@ -196,7 +195,7 @@ function General() {
} finally {
setIsCheckingUpdate(false)
}
}
}, [setIsCheckingUpdate, checkForUpdate])
return (
<div className="flex flex-col h-full">