ci: tauri build macos (#5184)
* ci: tauri build macos * chore: comment out electron builder .zip.sig file to s3 * chore: enable auto updater tauri * chore: comment out s3 upload mac.zip.sig * chore: handle remind me later state * chore: add dll file windows * chore: add debug step verbose * ci: add msvcp140_codecvt_ids.dll bundle windows * chore: update download progress * chore: update app updater UI * chore: remove log * chore: reload app after download app * chore: reset remindmelater
This commit is contained in:
parent
7dc51c5e0f
commit
9c825956e8
@ -243,7 +243,7 @@ jobs:
|
|||||||
aws s3 cp ./macos/latest-mac.yml s3://${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}/temp-${{ inputs.channel }}/latest-mac.yml
|
aws s3 cp ./macos/latest-mac.yml s3://${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}/temp-${{ inputs.channel }}/latest-mac.yml
|
||||||
aws s3 cp ./macos/beta-mac.yml s3://${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}/temp-${{ inputs.channel }}/beta-mac.yml
|
aws s3 cp ./macos/beta-mac.yml s3://${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}/temp-${{ inputs.channel }}/beta-mac.yml
|
||||||
aws s3 cp ./macos/jan-${{ inputs.channel }}-mac-universal-${{ inputs.new_version }}.zip s3://${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}/temp-${{ inputs.channel }}/jan-${{ inputs.channel }}-mac-universal-${{ inputs.new_version }}.zip
|
aws s3 cp ./macos/jan-${{ inputs.channel }}-mac-universal-${{ inputs.new_version }}.zip s3://${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}/temp-${{ inputs.channel }}/jan-${{ inputs.channel }}-mac-universal-${{ inputs.new_version }}.zip
|
||||||
aws s3 cp ./macos/jan-${{ inputs.channel }}-mac-universal-${{ inputs.new_version }}.zip.sig s3://${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}/temp-${{ inputs.channel }}/jan-${{ inputs.channel }}-mac-universal-${{ inputs.new_version }}.zip.sig
|
# aws s3 cp ./macos/jan-${{ inputs.channel }}-mac-universal-${{ inputs.new_version }}.zip.sig s3://${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}/temp-${{ inputs.channel }}/jan-${{ inputs.channel }}-mac-universal-${{ inputs.new_version }}.zip.sig
|
||||||
|
|
||||||
# Upload for tauri updater
|
# Upload for tauri updater
|
||||||
aws s3 cp ./dmg/Jan-${{ inputs.channel }}_${{ inputs.new_version }}_universal.dmg s3://${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}/temp-${{ inputs.channel }}/Jan-${{ inputs.channel }}_${{ inputs.new_version }}_universal.dmg
|
aws s3 cp ./dmg/Jan-${{ inputs.channel }}_${{ inputs.new_version }}_universal.dmg s3://${{ secrets.DELTA_AWS_S3_BUCKET_NAME }}/temp-${{ inputs.channel }}/Jan-${{ inputs.channel }}_${{ inputs.new_version }}_universal.dmg
|
||||||
|
|||||||
@ -171,6 +171,9 @@ jobs:
|
|||||||
- name: Build app
|
- name: Build app
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
curl -L -o ./src-tauri/binaries/vcomp140.dll https://catalog.jan.ai/vcomp140.dll
|
||||||
|
curl -L -o ./src-tauri/binaries/msvcp140_codecvt_ids.dll https://catalog.jan.ai/msvcp140_codecvt_ids.dll
|
||||||
|
ls ./src-tauri/binaries
|
||||||
make build-tauri
|
make build-tauri
|
||||||
env:
|
env:
|
||||||
AZURE_KEY_VAULT_URI: ${{ secrets.AZURE_KEY_VAULT_URI }}
|
AZURE_KEY_VAULT_URI: ${{ secrets.AZURE_KEY_VAULT_URI }}
|
||||||
|
|||||||
@ -640,7 +640,8 @@ Section Install
|
|||||||
File /a "/oname=cublasLt64_12.dll" "D:\a\jan\jan\src-tauri\binaries\cublasLt64_12.dll"
|
File /a "/oname=cublasLt64_12.dll" "D:\a\jan\jan\src-tauri\binaries\cublasLt64_12.dll"
|
||||||
File /a "/oname=cudart64_12.dll" "D:\a\jan\jan\src-tauri\binaries\cudart64_12.dll"
|
File /a "/oname=cudart64_12.dll" "D:\a\jan\jan\src-tauri\binaries\cudart64_12.dll"
|
||||||
File /a "/oname=msvcp140.dll" "D:\a\jan\jan\src-tauri\binaries\msvcp140.dll"
|
File /a "/oname=msvcp140.dll" "D:\a\jan\jan\src-tauri\binaries\msvcp140.dll"
|
||||||
; File /a "/oname=vcomp140.dll" "D:\a\jan\jan\src-tauri\binaries\vcomp140.dll"
|
File /a "/oname=vcomp140.dll" "D:\a\jan\jan\src-tauri\binaries\vcomp140.dll"
|
||||||
|
File /a "/oname=msvcp140_codecvt_ids.dll" "D:\a\jan\jan\src-tauri\binaries\msvcp140_codecvt_ids.dll"
|
||||||
File /a "/oname=vcruntime140_1.dll" "D:\a\jan\jan\src-tauri\binaries\vcruntime140_1.dll"
|
File /a "/oname=vcruntime140_1.dll" "D:\a\jan\jan\src-tauri\binaries\vcruntime140_1.dll"
|
||||||
File /a "/oname=vcruntime140.dll" "D:\a\jan\jan\src-tauri\binaries\vcruntime140.dll"
|
File /a "/oname=vcruntime140.dll" "D:\a\jan\jan\src-tauri\binaries\vcruntime140.dll"
|
||||||
File /a "/oname=vulkan-1.dll" "D:\a\jan\jan\src-tauri\binaries\vulkan-1.dll"
|
File /a "/oname=vulkan-1.dll" "D:\a\jan\jan\src-tauri\binaries\vulkan-1.dll"
|
||||||
|
|||||||
@ -74,7 +74,7 @@
|
|||||||
"bundle": {
|
"bundle": {
|
||||||
"active": true,
|
"active": true,
|
||||||
"targets": ["nsis", "app", "dmg", "deb", "appimage"],
|
"targets": ["nsis", "app", "dmg", "deb", "appimage"],
|
||||||
"createUpdaterArtifacts": false,
|
"createUpdaterArtifacts": true,
|
||||||
"icon": [
|
"icon": [
|
||||||
"icons/32x32.png",
|
"icons/32x32.png",
|
||||||
"icons/128x128.png",
|
"icons/128x128.png",
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { useModelProvider } from '@/hooks/useModelProvider'
|
|||||||
import { useAppUpdater } from '@/hooks/useAppUpdater'
|
import { useAppUpdater } from '@/hooks/useAppUpdater'
|
||||||
import { abortDownload } from '@/services/models'
|
import { abortDownload } from '@/services/models'
|
||||||
import { getProviders } from '@/services/providers'
|
import { getProviders } from '@/services/providers'
|
||||||
import { DownloadEvent, DownloadState, events } from '@janhq/core'
|
import { DownloadEvent, DownloadState, events, AppEvent } from '@janhq/core'
|
||||||
import { IconDownload, IconX } from '@tabler/icons-react'
|
import { IconDownload, IconX } from '@tabler/icons-react'
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
import { toast } from 'sonner'
|
import { toast } from 'sonner'
|
||||||
@ -21,10 +21,67 @@ export function DownloadManagement() {
|
|||||||
const [isPopoverOpen, setIsPopoverOpen] = useState(false)
|
const [isPopoverOpen, setIsPopoverOpen] = useState(false)
|
||||||
const { downloads, updateProgress, removeDownload } = useDownloadStore()
|
const { downloads, updateProgress, removeDownload } = useDownloadStore()
|
||||||
const { updateState } = useAppUpdater()
|
const { updateState } = useAppUpdater()
|
||||||
const downloadCount = useMemo(
|
|
||||||
() => Object.keys(downloads).length,
|
const [appUpdateState, setAppUpdateState] = useState({
|
||||||
[downloads]
|
isDownloading: false,
|
||||||
|
downloadProgress: 0,
|
||||||
|
downloadedBytes: 0,
|
||||||
|
totalBytes: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setAppUpdateState({
|
||||||
|
isDownloading: updateState.isDownloading,
|
||||||
|
downloadProgress: updateState.downloadProgress,
|
||||||
|
downloadedBytes: updateState.downloadedBytes,
|
||||||
|
totalBytes: updateState.totalBytes,
|
||||||
|
})
|
||||||
|
}, [updateState])
|
||||||
|
|
||||||
|
const onAppUpdateDownloadUpdate = useCallback(
|
||||||
|
(data: {
|
||||||
|
progress?: number
|
||||||
|
downloadedBytes?: number
|
||||||
|
totalBytes?: number
|
||||||
|
}) => {
|
||||||
|
setAppUpdateState((prev) => ({
|
||||||
|
...prev,
|
||||||
|
isDownloading: true,
|
||||||
|
downloadProgress: data.progress || 0,
|
||||||
|
downloadedBytes: data.downloadedBytes || 0,
|
||||||
|
totalBytes: data.totalBytes || 0,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const onAppUpdateDownloadSuccess = useCallback(() => {
|
||||||
|
setAppUpdateState((prev) => ({
|
||||||
|
...prev,
|
||||||
|
isDownloading: false,
|
||||||
|
downloadProgress: 1,
|
||||||
|
}))
|
||||||
|
toast.success('App Update Downloaded', {
|
||||||
|
description: 'The app update has been downloaded successfully.',
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const onAppUpdateDownloadError = useCallback(() => {
|
||||||
|
setAppUpdateState((prev) => ({
|
||||||
|
...prev,
|
||||||
|
isDownloading: false,
|
||||||
|
}))
|
||||||
|
toast.error('App Update Download Failed', {
|
||||||
|
description: 'Failed to download the app update. Please try again.',
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const downloadCount = useMemo(() => {
|
||||||
|
const modelDownloads = Object.keys(downloads).length
|
||||||
|
const appUpdateDownload = appUpdateState.isDownloading ? 1 : 0
|
||||||
|
const total = modelDownloads + appUpdateDownload
|
||||||
|
return total
|
||||||
|
}, [downloads, appUpdateState.isDownloading])
|
||||||
const downloadProcesses = useMemo(
|
const downloadProcesses = useMemo(
|
||||||
() =>
|
() =>
|
||||||
Object.values(downloads).map((download) => ({
|
Object.values(downloads).map((download) => ({
|
||||||
@ -38,14 +95,31 @@ export function DownloadManagement() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const overallProgress = useMemo(() => {
|
const overallProgress = useMemo(() => {
|
||||||
const total = downloadProcesses.reduce((acc, download) => {
|
const modelTotal = downloadProcesses.reduce((acc, download) => {
|
||||||
return acc + download.total
|
return acc + download.total
|
||||||
}, 0)
|
}, 0)
|
||||||
const current = downloadProcesses.reduce((acc, download) => {
|
const modelCurrent = downloadProcesses.reduce((acc, download) => {
|
||||||
return acc + download.current
|
return acc + download.current
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
|
// Include app update progress in overall calculation
|
||||||
|
const appUpdateTotal = appUpdateState.isDownloading
|
||||||
|
? appUpdateState.totalBytes
|
||||||
|
: 0
|
||||||
|
const appUpdateCurrent = appUpdateState.isDownloading
|
||||||
|
? appUpdateState.downloadedBytes
|
||||||
|
: 0
|
||||||
|
|
||||||
|
const total = modelTotal + appUpdateTotal
|
||||||
|
const current = modelCurrent + appUpdateCurrent
|
||||||
|
|
||||||
return total > 0 ? current / total : 0
|
return total > 0 ? current / total : 0
|
||||||
}, [downloadProcesses])
|
}, [
|
||||||
|
downloadProcesses,
|
||||||
|
appUpdateState.isDownloading,
|
||||||
|
appUpdateState.totalBytes,
|
||||||
|
appUpdateState.downloadedBytes,
|
||||||
|
])
|
||||||
|
|
||||||
const onFileDownloadUpdate = useCallback(
|
const onFileDownloadUpdate = useCallback(
|
||||||
async (state: DownloadState) => {
|
async (state: DownloadState) => {
|
||||||
@ -97,18 +171,34 @@ export function DownloadManagement() {
|
|||||||
events.on(DownloadEvent.onFileDownloadSuccess, onFileDownloadSuccess)
|
events.on(DownloadEvent.onFileDownloadSuccess, onFileDownloadSuccess)
|
||||||
events.on(DownloadEvent.onFileDownloadStopped, onFileDownloadStopped)
|
events.on(DownloadEvent.onFileDownloadStopped, onFileDownloadStopped)
|
||||||
|
|
||||||
|
// Register app update event listeners
|
||||||
|
events.on(AppEvent.onAppUpdateDownloadUpdate, onAppUpdateDownloadUpdate)
|
||||||
|
events.on(AppEvent.onAppUpdateDownloadSuccess, onAppUpdateDownloadSuccess)
|
||||||
|
events.on(AppEvent.onAppUpdateDownloadError, onAppUpdateDownloadError)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
console.debug('DownloadListener: unregistering event listeners...')
|
console.debug('DownloadListener: unregistering event listeners...')
|
||||||
events.off(DownloadEvent.onFileDownloadUpdate, onFileDownloadUpdate)
|
events.off(DownloadEvent.onFileDownloadUpdate, onFileDownloadUpdate)
|
||||||
events.off(DownloadEvent.onFileDownloadError, onFileDownloadError)
|
events.off(DownloadEvent.onFileDownloadError, onFileDownloadError)
|
||||||
events.off(DownloadEvent.onFileDownloadSuccess, onFileDownloadSuccess)
|
events.off(DownloadEvent.onFileDownloadSuccess, onFileDownloadSuccess)
|
||||||
events.off(DownloadEvent.onFileDownloadStopped, onFileDownloadStopped)
|
events.off(DownloadEvent.onFileDownloadStopped, onFileDownloadStopped)
|
||||||
|
|
||||||
|
// Unregister app update event listeners
|
||||||
|
events.off(AppEvent.onAppUpdateDownloadUpdate, onAppUpdateDownloadUpdate)
|
||||||
|
events.off(
|
||||||
|
AppEvent.onAppUpdateDownloadSuccess,
|
||||||
|
onAppUpdateDownloadSuccess
|
||||||
|
)
|
||||||
|
events.off(AppEvent.onAppUpdateDownloadError, onAppUpdateDownloadError)
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
onFileDownloadUpdate,
|
onFileDownloadUpdate,
|
||||||
onFileDownloadError,
|
onFileDownloadError,
|
||||||
onFileDownloadSuccess,
|
onFileDownloadSuccess,
|
||||||
onFileDownloadStopped,
|
onFileDownloadStopped,
|
||||||
|
onAppUpdateDownloadUpdate,
|
||||||
|
onAppUpdateDownloadSuccess,
|
||||||
|
onAppUpdateDownloadError,
|
||||||
])
|
])
|
||||||
|
|
||||||
function renderGB(bytes: number): string {
|
function renderGB(bytes: number): string {
|
||||||
@ -118,8 +208,7 @@ export function DownloadManagement() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{(downloadCount > 0 ||
|
{downloadCount > 0 && (
|
||||||
(updateState.isDownloading && updateState.downloadProgress > 0)) && (
|
|
||||||
<Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen}>
|
<Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen}>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
{isLeftPanelOpen ? (
|
{isLeftPanelOpen ? (
|
||||||
@ -162,24 +251,23 @@ export function DownloadManagement() {
|
|||||||
<p className="text-xs text-main-view-fg/70">Downloading</p>
|
<p className="text-xs text-main-view-fg/70">Downloading</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-2 max-h-[300px] overflow-y-auto space-y-2">
|
<div className="p-2 max-h-[300px] overflow-y-auto space-y-2">
|
||||||
{!updateState.isDownloading &&
|
{appUpdateState.isDownloading && (
|
||||||
updateState.downloadProgress > 0 && (
|
<div className="bg-main-view-fg/4 rounded-md p-2">
|
||||||
<div className="bg-main-view-fg/4 rounded-md p-2">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center justify-between">
|
<p className="truncate text-main-view-fg/80">
|
||||||
<p className="truncate text-main-view-fg/80">
|
App Update
|
||||||
App Update
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<Progress
|
|
||||||
value={updateState.downloadProgress * 100}
|
|
||||||
className="my-2"
|
|
||||||
/>
|
|
||||||
<p className="text-main-view-fg/60 text-xs">
|
|
||||||
{`${renderGB(updateState.downloadedBytes)} / ${renderGB(updateState.totalBytes)}`}{' '}
|
|
||||||
GB ({Math.round(updateState.downloadProgress * 100)}%)
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
<Progress
|
||||||
|
value={appUpdateState.downloadProgress * 100}
|
||||||
|
className="my-2"
|
||||||
|
/>
|
||||||
|
<p className="text-main-view-fg/60 text-xs">
|
||||||
|
{`${renderGB(appUpdateState.downloadedBytes)} / ${renderGB(appUpdateState.totalBytes)}`}{' '}
|
||||||
|
GB ({Math.round(appUpdateState.downloadProgress * 100)}%)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{downloadProcesses.map((download) => (
|
{downloadProcesses.map((download) => (
|
||||||
<div className="bg-main-view-fg/4 rounded-md p-2">
|
<div className="bg-main-view-fg/4 rounded-md p-2">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
|
|||||||
@ -9,10 +9,13 @@ import { RenderMarkdown } from '../RenderMarkdown'
|
|||||||
import { isDev } from '@/lib/utils'
|
import { isDev } from '@/lib/utils'
|
||||||
|
|
||||||
const DialogAppUpdater = () => {
|
const DialogAppUpdater = () => {
|
||||||
const { updateState, downloadAndInstallUpdate, checkForUpdate } =
|
const {
|
||||||
useAppUpdater()
|
updateState,
|
||||||
|
downloadAndInstallUpdate,
|
||||||
|
checkForUpdate,
|
||||||
|
setRemindMeLater,
|
||||||
|
} = useAppUpdater()
|
||||||
const [showReleaseNotes, setShowReleaseNotes] = useState(false)
|
const [showReleaseNotes, setShowReleaseNotes] = useState(false)
|
||||||
const [remindMeLater, setRemindMeLater] = useState(false)
|
|
||||||
|
|
||||||
const handleUpdate = () => {
|
const handleUpdate = () => {
|
||||||
downloadAndInstallUpdate()
|
downloadAndInstallUpdate()
|
||||||
@ -35,7 +38,7 @@ const DialogAppUpdater = () => {
|
|||||||
checkForUpdate()
|
checkForUpdate()
|
||||||
}, [checkForUpdate])
|
}, [checkForUpdate])
|
||||||
|
|
||||||
if (remindMeLater) return null
|
if (updateState.remindMeLater) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { isDev } from '@/lib/utils'
|
import { isDev } from '@/lib/utils'
|
||||||
import { check, Update } from '@tauri-apps/plugin-updater'
|
import { check, Update } from '@tauri-apps/plugin-updater'
|
||||||
import { useState, useCallback } from 'react'
|
import { useState, useCallback } from 'react'
|
||||||
|
import { events, AppEvent } from '@janhq/core'
|
||||||
|
|
||||||
export interface UpdateState {
|
export interface UpdateState {
|
||||||
isUpdateAvailable: boolean
|
isUpdateAvailable: boolean
|
||||||
@ -9,6 +10,7 @@ export interface UpdateState {
|
|||||||
downloadProgress: number
|
downloadProgress: number
|
||||||
downloadedBytes: number
|
downloadedBytes: number
|
||||||
totalBytes: number
|
totalBytes: number
|
||||||
|
remindMeLater: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useAppUpdater = () => {
|
export const useAppUpdater = () => {
|
||||||
@ -19,10 +21,19 @@ export const useAppUpdater = () => {
|
|||||||
downloadProgress: 0,
|
downloadProgress: 0,
|
||||||
downloadedBytes: 0,
|
downloadedBytes: 0,
|
||||||
totalBytes: 0,
|
totalBytes: 0,
|
||||||
|
remindMeLater: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const checkForUpdate = useCallback(async () => {
|
const checkForUpdate = useCallback(async (resetRemindMeLater = false) => {
|
||||||
try {
|
try {
|
||||||
|
// Reset remindMeLater if requested (e.g., when called from settings)
|
||||||
|
if (resetRemindMeLater) {
|
||||||
|
setUpdateState((prev) => ({
|
||||||
|
...prev,
|
||||||
|
remindMeLater: false,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
if (!isDev()) {
|
if (!isDev()) {
|
||||||
// Production mode - use actual Tauri updater
|
// Production mode - use actual Tauri updater
|
||||||
const update = await check()
|
const update = await check()
|
||||||
@ -45,6 +56,13 @@ export const useAppUpdater = () => {
|
|||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
setUpdateState((prev) => ({
|
||||||
|
...prev,
|
||||||
|
isUpdateAvailable: false,
|
||||||
|
updateInfo: null,
|
||||||
|
}))
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error checking for updates:', error)
|
console.error('Error checking for updates:', error)
|
||||||
@ -58,6 +76,13 @@ export const useAppUpdater = () => {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const setRemindMeLater = useCallback((remind: boolean) => {
|
||||||
|
setUpdateState((prev) => ({
|
||||||
|
...prev,
|
||||||
|
remindMeLater: remind,
|
||||||
|
}))
|
||||||
|
}, [])
|
||||||
|
|
||||||
const downloadAndInstallUpdate = useCallback(async () => {
|
const downloadAndInstallUpdate = useCallback(async () => {
|
||||||
if (!updateState.updateInfo) return
|
if (!updateState.updateInfo) return
|
||||||
|
|
||||||
@ -79,6 +104,13 @@ export const useAppUpdater = () => {
|
|||||||
totalBytes: contentLength,
|
totalBytes: contentLength,
|
||||||
}))
|
}))
|
||||||
console.log(`Started downloading ${contentLength} bytes`)
|
console.log(`Started downloading ${contentLength} bytes`)
|
||||||
|
|
||||||
|
// Emit app update download started event
|
||||||
|
events.emit(AppEvent.onAppUpdateDownloadUpdate, {
|
||||||
|
progress: 0,
|
||||||
|
downloadedBytes: 0,
|
||||||
|
totalBytes: contentLength,
|
||||||
|
})
|
||||||
break
|
break
|
||||||
case 'Progress': {
|
case 'Progress': {
|
||||||
downloaded += event.data.chunkLength
|
downloaded += event.data.chunkLength
|
||||||
@ -89,6 +121,13 @@ export const useAppUpdater = () => {
|
|||||||
downloadedBytes: downloaded,
|
downloadedBytes: downloaded,
|
||||||
}))
|
}))
|
||||||
console.log(`Downloaded ${downloaded} from ${contentLength}`)
|
console.log(`Downloaded ${downloaded} from ${contentLength}`)
|
||||||
|
|
||||||
|
// Emit app update download progress event
|
||||||
|
events.emit(AppEvent.onAppUpdateDownloadUpdate, {
|
||||||
|
progress: progress,
|
||||||
|
downloadedBytes: downloaded,
|
||||||
|
totalBytes: contentLength,
|
||||||
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'Finished':
|
case 'Finished':
|
||||||
@ -98,10 +137,15 @@ export const useAppUpdater = () => {
|
|||||||
isDownloading: false,
|
isDownloading: false,
|
||||||
downloadProgress: 1,
|
downloadProgress: 1,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// Emit app update download success event
|
||||||
|
events.emit(AppEvent.onAppUpdateDownloadSuccess, {})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await window.core?.api?.relaunch()
|
||||||
|
|
||||||
console.log('Update installed')
|
console.log('Update installed')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error downloading update:', error)
|
console.error('Error downloading update:', error)
|
||||||
@ -109,6 +153,11 @@ export const useAppUpdater = () => {
|
|||||||
...prev,
|
...prev,
|
||||||
isDownloading: false,
|
isDownloading: false,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// Emit app update download error event
|
||||||
|
events.emit(AppEvent.onAppUpdateDownloadError, {
|
||||||
|
message: error instanceof Error ? error.message : 'Unknown error',
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}, [updateState.updateInfo])
|
}, [updateState.updateInfo])
|
||||||
|
|
||||||
@ -116,5 +165,6 @@ export const useAppUpdater = () => {
|
|||||||
updateState,
|
updateState,
|
||||||
checkForUpdate,
|
checkForUpdate,
|
||||||
downloadAndInstallUpdate,
|
downloadAndInstallUpdate,
|
||||||
|
setRemindMeLater,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,7 +63,7 @@ const openFileTitle = (): string => {
|
|||||||
function General() {
|
function General() {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { spellCheckChatInput, setSpellCheckChatInput } = useGeneralSetting()
|
const { spellCheckChatInput, setSpellCheckChatInput } = useGeneralSetting()
|
||||||
const { checkForUpdate } = useAppUpdater()
|
const { checkForUpdate, setRemindMeLater } = useAppUpdater()
|
||||||
const [janDataFolder, setJanDataFolder] = useState<string | undefined>()
|
const [janDataFolder, setJanDataFolder] = useState<string | undefined>()
|
||||||
const [isCopied, setIsCopied] = useState(false)
|
const [isCopied, setIsCopied] = useState(false)
|
||||||
const [selectedNewPath, setSelectedNewPath] = useState<string | null>(null)
|
const [selectedNewPath, setSelectedNewPath] = useState<string | null>(null)
|
||||||
@ -181,10 +181,11 @@ function General() {
|
|||||||
|
|
||||||
const handleCheckForUpdate = async () => {
|
const handleCheckForUpdate = async () => {
|
||||||
setIsCheckingUpdate(true)
|
setIsCheckingUpdate(true)
|
||||||
|
setRemindMeLater(false)
|
||||||
try {
|
try {
|
||||||
if (isDev())
|
if (isDev())
|
||||||
return toast.info('You are running a development version of Jan!')
|
return toast.info('You are running a development version of Jan!')
|
||||||
const update = await checkForUpdate()
|
const update = await checkForUpdate(true)
|
||||||
if (!update) {
|
if (!update) {
|
||||||
toast.info('You are using the latest version of Jan!')
|
toast.info('You are using the latest version of Jan!')
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user