mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-22 08:40:08 +08:00
feat: add data limit warning notification (#8866)
* feat: add disk space checking functionality - Introduced a new IPC channel for retrieving disk information. - Integrated the 'check-disk-space' package to fetch available and total disk space. - Updated the preload API to expose the new disk info retrieval method to the renderer. * feat: implement disk space warning and data limit checks - Added functionality to check available disk space and display warnings when storage is low. - Updated IPC methods to pass directory paths for disk info retrieval. - Introduced periodic checks for app data disk quota and internal storage quota. - Enhanced user notifications with localized messages for low storage warnings. * fix: enhance disk space warning logic and improve logging - Added additional conditions for displaying disk space warnings based on free percentage thresholds. - Improved logging format for app data disk quota, providing clearer output in GB. - Refactored the checkDataLimit function to be asynchronous for better performance. * format code * update log format * fix: improve error handling and logging in disk quota checks - Added try-catch block in checkAppDataDiskQuota to handle potential errors when retrieving disk information. - Ensured that errors are logged for better debugging and visibility. - Updated checkDataLimit to await the checkAppDataDiskQuota function for proper asynchronous handling. * fix comments * fix: remove redundant appStorageQuota message from localization files * lint * fix: enhance disk space warning logic for USB disks - Added a condition to warn users when free space on USB disks falls below 5% of total capacity. - Improved the existing logic for displaying disk space warnings based on total disk size thresholds. * update i18n * Refactor data limit notification logic and update i18n messages for disk space warnings. Adjusted check intervals and improved toast notifications for low disk space alerts. * Fix disk quota check logic in useDataLimit hook to correctly compare free space against 1GB threshold. * refactor: update styles and improve navbar handling - Removed unnecessary margin-bottom style from bubble markdown. - Adjusted margin in Prompt component for better layout. - Enhanced useAppInit hook to include navbar position logic for background styling. - Added alignment to ErrorBlock alert for improved visual consistency. * refactor: relocate checkDataLimit function to utils and update import in useAppInit hook - Moved checkDataLimit function from useDataLimit hook to utils for better organization. - Updated import path in useAppInit to reflect the new location of checkDataLimit. - Removed the now obsolete useDataLimit hook file. * refactor: update getDiskInfo API to specify return type - Enhanced getDiskInfo function to explicitly define the return type as a Promise containing disk information or null. * lint err * fix: handle null response from getDiskInfo in checkAppDataDiskQuota - Added a check for null response from getDiskInfo to prevent errors. - Updated the logic to extract the free disk space only if diskInfo is valid. --------- Co-authored-by: kangfenmao <kangfenmao@qq.com>
This commit is contained in:
parent
6104b7803b
commit
871565c687
@ -220,6 +220,7 @@
|
||||
"axios": "^1.7.3",
|
||||
"browser-image-compression": "^2.0.2",
|
||||
"chardet": "^2.1.0",
|
||||
"check-disk-space": "3.4.0",
|
||||
"cheerio": "^1.1.2",
|
||||
"chokidar": "^4.0.3",
|
||||
"cli-progress": "^3.12.0",
|
||||
|
||||
@ -35,6 +35,7 @@ export enum IpcChannel {
|
||||
App_InstallBunBinary = 'app:install-bun-binary',
|
||||
App_LogToMain = 'app:log-to-main',
|
||||
App_SaveData = 'app:save-data',
|
||||
App_GetDiskInfo = 'app:get-disk-info',
|
||||
App_SetFullScreen = 'app:set-full-screen',
|
||||
App_IsFullScreen = 'app:is-full-screen',
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ import { SpanEntity, TokenUsage } from '@mcp-trace/trace-core'
|
||||
import { MIN_WINDOW_HEIGHT, MIN_WINDOW_WIDTH, UpgradeChannel } from '@shared/config/constant'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import { FileMetadata, Provider, Shortcut, ThemeMode } from '@types'
|
||||
import checkDiskSpace from 'check-disk-space'
|
||||
import { BrowserWindow, dialog, ipcMain, ProxyConfig, session, shell, systemPreferences, webContents } from 'electron'
|
||||
import { Notification } from 'src/renderer/src/types/notification'
|
||||
|
||||
@ -783,6 +784,20 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
|
||||
addStreamMessage(spanId, modelName, context, msg)
|
||||
)
|
||||
|
||||
ipcMain.handle(IpcChannel.App_GetDiskInfo, async (_, directoryPath: string) => {
|
||||
try {
|
||||
const diskSpace = await checkDiskSpace(directoryPath) // { free, size } in bytes
|
||||
logger.debug('disk space', diskSpace)
|
||||
const { free, size } = diskSpace
|
||||
return {
|
||||
free,
|
||||
size
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('check disk space error', error as Error)
|
||||
return null
|
||||
}
|
||||
})
|
||||
// API Server
|
||||
apiServerService.registerIpcHandlers()
|
||||
|
||||
|
||||
@ -44,6 +44,8 @@ export function tracedInvoke(channel: string, spanContext: SpanContext | undefin
|
||||
// Custom APIs for renderer
|
||||
const api = {
|
||||
getAppInfo: () => ipcRenderer.invoke(IpcChannel.App_Info),
|
||||
getDiskInfo: (directoryPath: string): Promise<{ free: number; size: number } | null> =>
|
||||
ipcRenderer.invoke(IpcChannel.App_GetDiskInfo, directoryPath),
|
||||
reload: () => ipcRenderer.invoke(IpcChannel.App_Reload),
|
||||
setProxy: (proxy: string | undefined, bypassRules?: string) =>
|
||||
ipcRenderer.invoke(IpcChannel.App_Proxy, proxy, bypassRules),
|
||||
|
||||
@ -12,6 +12,7 @@ import { handleSaveData } from '@renderer/store'
|
||||
import { selectMemoryConfig } from '@renderer/store/memory'
|
||||
import { setAvatar, setFilesPath, setResourcesPath, setUpdateState } from '@renderer/store/runtime'
|
||||
import { delay, runAsyncFunction } from '@renderer/utils'
|
||||
import { checkDataLimit } from '@renderer/utils'
|
||||
import { defaultLanguage } from '@shared/config/constant'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import { useLiveQuery } from 'dexie-react-hooks'
|
||||
@ -159,4 +160,8 @@ export function useAppInit() {
|
||||
logger.error('Failed to update memory config:', error)
|
||||
})
|
||||
}, [memoryConfig])
|
||||
|
||||
useEffect(() => {
|
||||
checkDataLimit()
|
||||
}, [])
|
||||
}
|
||||
|
||||
@ -2650,6 +2650,10 @@
|
||||
"url": "Joplin Web Clipper Service URL",
|
||||
"url_placeholder": "http://127.0.0.1:41184/"
|
||||
},
|
||||
"limit": {
|
||||
"appDataDiskQuota": "Disk Space Warning",
|
||||
"appDataDiskQuotaDescription": "Data directory space is almost full, please clear disk space, otherwise data will be lost"
|
||||
},
|
||||
"local": {
|
||||
"autoSync": {
|
||||
"label": "Auto Backup",
|
||||
|
||||
@ -132,6 +132,7 @@
|
||||
},
|
||||
"title": "API 服务器"
|
||||
},
|
||||
|
||||
"assistants": {
|
||||
"abbr": "助手",
|
||||
"clear": {
|
||||
@ -2650,6 +2651,10 @@
|
||||
"url": "Joplin 剪裁服务监听 URL",
|
||||
"url_placeholder": "http://127.0.0.1:41184/"
|
||||
},
|
||||
"limit": {
|
||||
"appDataDiskQuota": "磁盘空间警告",
|
||||
"appDataDiskQuotaDescription": "数据目录空间即将用尽, 请清理磁盘空间, 否则会丢失数据"
|
||||
},
|
||||
"local": {
|
||||
"autoSync": {
|
||||
"label": "自动备份",
|
||||
|
||||
@ -2650,6 +2650,10 @@
|
||||
"url": "Joplin 剪輯服務 URL",
|
||||
"url_placeholder": "http://127.0.0.1:41184/"
|
||||
},
|
||||
"limit": {
|
||||
"appDataDiskQuota": "磁碟空間警告",
|
||||
"appDataDiskQuotaDescription": "資料目錄空間即將用盡, 請清理磁碟空間, 否則會丟失數據"
|
||||
},
|
||||
"local": {
|
||||
"autoSync": {
|
||||
"label": "自動備份",
|
||||
|
||||
@ -538,6 +538,10 @@
|
||||
"tip": "Στη γραμμή εργαλείων των εκτελέσιμων blocks κώδικα θα εμφανίζεται το κουμπί εκτέλεσης· προσέξτε να μην εκτελέσετε επικίνδυνο κώδικα!",
|
||||
"title": "Εκτέλεση Κώδικα"
|
||||
},
|
||||
"code_fancy_block": {
|
||||
"label": "[to be translated]:花式代码块",
|
||||
"tip": "[to be translated]:使用更美观的代码块样式,例如 HTML 卡片"
|
||||
},
|
||||
"code_image_tools": {
|
||||
"label": "Ενεργοποίηση εργαλείου προεπισκόπησης",
|
||||
"tip": "Ενεργοποίηση εργαλείου προεπισκόπησης για εικόνες που αποδίδονται από blocks κώδικα όπως το mermaid"
|
||||
@ -1741,8 +1745,15 @@
|
||||
"compress_content": "μείωση πλάτους στήλης",
|
||||
"compress_content_description": "Ενεργοποιώντας το, θα περιορίζεται ο αριθμός των χαρακτήρων ανά γραμμή, μειώνοντας την οθόνη που εμφανίζεται",
|
||||
"default_font": "προεπιλεγμένη γραμματοσειρά",
|
||||
"font_size": "[to be translated]:字体大小",
|
||||
"font_size_description": "[to be translated]:调整字体大小以获得更好的阅读体验 (10-30px)",
|
||||
"font_size_large": "[to be translated]:大",
|
||||
"font_size_medium": "[to be translated]:中",
|
||||
"font_size_small": "[to be translated]:小",
|
||||
"font_title": "ρυθμίσεις γραμματοσειράς",
|
||||
"serif_font": "σειρά γραμματοσειρών",
|
||||
"show_table_of_contents": "[to be translated]:显示目录大纲",
|
||||
"show_table_of_contents_description": "[to be translated]:显示目录大纲侧边栏,方便文档内导航",
|
||||
"title": "ρυθμίσεις εμφάνισης"
|
||||
},
|
||||
"editor": {
|
||||
@ -2639,6 +2650,10 @@
|
||||
"url": "URL υπηρεσίας περικοπής Joplin",
|
||||
"url_placeholder": "http://127.0.0.1:41184/"
|
||||
},
|
||||
"limit": {
|
||||
"appDataDiskQuota": "Προειδοποίηση χώρου δίσκου",
|
||||
"appDataDiskQuotaDescription": "Ο κατάλογος δεδομένων της εφαρμογής είναι σχεδόν γεμάτος, παρακαλώ απομακρύνετε τον χώρο δίσκου, αλλιώς θα χαθούν τα δεδομένα"
|
||||
},
|
||||
"local": {
|
||||
"autoSync": {
|
||||
"label": "Αυτόματο αντίγραφο ασφαλείας",
|
||||
|
||||
@ -538,6 +538,10 @@
|
||||
"tip": "En la barra de herramientas de bloques de código ejecutables se mostrará un botón de ejecución. ¡Tenga cuidado en no ejecutar código peligroso!",
|
||||
"title": "Ejecución de Código"
|
||||
},
|
||||
"code_fancy_block": {
|
||||
"label": "[to be translated]:花式代码块",
|
||||
"tip": "[to be translated]:使用更美观的代码块样式,例如 HTML 卡片"
|
||||
},
|
||||
"code_image_tools": {
|
||||
"label": "Habilitar herramienta de vista previa",
|
||||
"tip": "Habilitar herramientas de vista previa para imágenes renderizadas de bloques de código como mermaid"
|
||||
@ -1741,8 +1745,15 @@
|
||||
"compress_content": "reducir el ancho de la columna",
|
||||
"compress_content_description": "Al activarlo, se limitará el número de caracteres por línea, reduciendo el contenido mostrado en pantalla.",
|
||||
"default_font": "fuente predeterminada",
|
||||
"font_size": "[to be translated]:字体大小",
|
||||
"font_size_description": "[to be translated]:调整字体大小以获得更好的阅读体验 (10-30px)",
|
||||
"font_size_large": "[to be translated]:大",
|
||||
"font_size_medium": "[to be translated]:中",
|
||||
"font_size_small": "[to be translated]:小",
|
||||
"font_title": "Configuración de fuente",
|
||||
"serif_font": "fuente serif",
|
||||
"show_table_of_contents": "[to be translated]:显示目录大纲",
|
||||
"show_table_of_contents_description": "[to be translated]:显示目录大纲侧边栏,方便文档内导航",
|
||||
"title": "configuración de visualización"
|
||||
},
|
||||
"editor": {
|
||||
@ -2639,6 +2650,10 @@
|
||||
"url": "URL a la que escucha el servicio de recorte de Joplin",
|
||||
"url_placeholder": "http://127.0.0.1:41184/"
|
||||
},
|
||||
"limit": {
|
||||
"appDataDiskQuota": "Advertencia de espacio en disco",
|
||||
"appDataDiskQuotaDescription": "El espacio de almacenamiento de datos está casi lleno, por favor, limpie el espacio en disco, de lo contrario, se perderán los datos"
|
||||
},
|
||||
"local": {
|
||||
"autoSync": {
|
||||
"label": "Copia de seguridad automática",
|
||||
|
||||
@ -538,6 +538,10 @@
|
||||
"tip": "Une bouton d'exécution s'affichera dans la barre d'outils des blocs de code exécutables. Attention à ne pas exécuter de code dangereux !",
|
||||
"title": "Exécution de code"
|
||||
},
|
||||
"code_fancy_block": {
|
||||
"label": "[to be translated]:花式代码块",
|
||||
"tip": "[to be translated]:使用更美观的代码块样式,例如 HTML 卡片"
|
||||
},
|
||||
"code_image_tools": {
|
||||
"label": "Activer l'outil d'aperçu",
|
||||
"tip": "Activer les outils de prévisualisation pour les images rendues des blocs de code tels que mermaid"
|
||||
@ -1741,8 +1745,15 @@
|
||||
"compress_content": "réduire la largeur des colonnes",
|
||||
"compress_content_description": "L'activation limitera le nombre de caractères par ligne, réduisant ainsi le contenu affiché à l'écran.",
|
||||
"default_font": "police par défaut",
|
||||
"font_size": "[to be translated]:字体大小",
|
||||
"font_size_description": "[to be translated]:调整字体大小以获得更好的阅读体验 (10-30px)",
|
||||
"font_size_large": "[to be translated]:大",
|
||||
"font_size_medium": "[to be translated]:中",
|
||||
"font_size_small": "[to be translated]:小",
|
||||
"font_title": "paramétrage des polices",
|
||||
"serif_font": "police à empattements",
|
||||
"show_table_of_contents": "[to be translated]:显示目录大纲",
|
||||
"show_table_of_contents_description": "[to be translated]:显示目录大纲侧边栏,方便文档内导航",
|
||||
"title": "Paramètres d'affichage"
|
||||
},
|
||||
"editor": {
|
||||
@ -2639,6 +2650,10 @@
|
||||
"url": "URL surveillée par le service de découpage de Joplin",
|
||||
"url_placeholder": "http://127.0.0.1:41184/"
|
||||
},
|
||||
"limit": {
|
||||
"appDataDiskQuota": "Avertissement d'espace sur le disque",
|
||||
"appDataDiskQuotaDescription": "L'espace de stockage des données est presque plein, veuillez nettoyer l'espace sur le disque, sinon les données seront perdues"
|
||||
},
|
||||
"local": {
|
||||
"autoSync": {
|
||||
"label": "Sauvegarde automatique",
|
||||
|
||||
@ -538,6 +538,10 @@
|
||||
"tip": "実行可能なコードブロックのツールバーには実行ボタンが表示されます。危険なコードを実行しないでください!",
|
||||
"title": "コード実行"
|
||||
},
|
||||
"code_fancy_block": {
|
||||
"label": "[to be translated]:花式代码块",
|
||||
"tip": "[to be translated]:使用更美观的代码块样式,例如 HTML 卡片"
|
||||
},
|
||||
"code_image_tools": {
|
||||
"label": "プレビューツールを有効にする",
|
||||
"tip": "mermaid などのコードブロックから生成された画像に対してプレビューツールを有効にする"
|
||||
@ -1741,8 +1745,15 @@
|
||||
"compress_content": "バーの幅を減らします",
|
||||
"compress_content_description": "有効にすると、1行あたりの単語数が制限され、画面に表示されるコンテンツが減少します。",
|
||||
"default_font": "デフォルトフォント",
|
||||
"font_size": "[to be translated]:字体大小",
|
||||
"font_size_description": "[to be translated]:调整字体大小以获得更好的阅读体验 (10-30px)",
|
||||
"font_size_large": "[to be translated]:大",
|
||||
"font_size_medium": "[to be translated]:中",
|
||||
"font_size_small": "[to be translated]:小",
|
||||
"font_title": "フォント設定",
|
||||
"serif_font": "セリフフォント",
|
||||
"show_table_of_contents": "[to be translated]:显示目录大纲",
|
||||
"show_table_of_contents_description": "[to be translated]:显示目录大纲侧边栏,方便文档内导航",
|
||||
"title": "見せる"
|
||||
},
|
||||
"editor": {
|
||||
@ -2639,6 +2650,10 @@
|
||||
"url": "Joplin 剪輯服務 URL",
|
||||
"url_placeholder": "http://127.0.0.1:41184/"
|
||||
},
|
||||
"limit": {
|
||||
"appDataDiskQuota": "ディスク容量警告",
|
||||
"appDataDiskQuotaDescription": "データディレクトリの容量がほぼ満杯になっており、新しいデータの保存ができなくなる可能性があります。まずデータをバックアップしてから、ディスク容量を整理してください。"
|
||||
},
|
||||
"local": {
|
||||
"autoSync": {
|
||||
"label": "自動バックアップ",
|
||||
|
||||
@ -538,6 +538,10 @@
|
||||
"tip": "A barra de ferramentas de blocos de código executáveis exibirá um botão de execução; atenção para não executar códigos perigosos!",
|
||||
"title": "Execução de Código"
|
||||
},
|
||||
"code_fancy_block": {
|
||||
"label": "[to be translated]:花式代码块",
|
||||
"tip": "[to be translated]:使用更美观的代码块样式,例如 HTML 卡片"
|
||||
},
|
||||
"code_image_tools": {
|
||||
"label": "Habilitar ferramenta de visualização",
|
||||
"tip": "Ativar ferramentas de visualização para imagens renderizadas de blocos de código como mermaid"
|
||||
@ -1741,8 +1745,15 @@
|
||||
"compress_content": "reduzir a largura da coluna",
|
||||
"compress_content_description": "Ativando isso limitará o número de caracteres por linha, reduzindo o conteúdo exibido na tela.",
|
||||
"default_font": "fonte padrão",
|
||||
"font_size": "[to be translated]:字体大小",
|
||||
"font_size_description": "[to be translated]:调整字体大小以获得更好的阅读体验 (10-30px)",
|
||||
"font_size_large": "[to be translated]:大",
|
||||
"font_size_medium": "[to be translated]:中",
|
||||
"font_size_small": "[to be translated]:小",
|
||||
"font_title": "configuração de fonte",
|
||||
"serif_font": "fonte com serifa",
|
||||
"show_table_of_contents": "[to be translated]:显示目录大纲",
|
||||
"show_table_of_contents_description": "[to be translated]:显示目录大纲侧边栏,方便文档内导航",
|
||||
"title": "configurações de exibição"
|
||||
},
|
||||
"editor": {
|
||||
@ -2639,6 +2650,10 @@
|
||||
"url": "URL para o qual o serviço de recorte do Joplin está escutando",
|
||||
"url_placeholder": "http://127.0.0.1:41184/"
|
||||
},
|
||||
"limit": {
|
||||
"appDataDiskQuota": "Aviso de espaço em disco",
|
||||
"appDataDiskQuotaDescription": "O espaço de armazenamento de dados está quase cheio, por favor, limpe o espaço em disco, caso contrário, os dados serão perdidos"
|
||||
},
|
||||
"local": {
|
||||
"autoSync": {
|
||||
"label": "Backup automático",
|
||||
|
||||
@ -538,6 +538,10 @@
|
||||
"tip": "Выполнение кода в блоке кода возможно, но не рекомендуется выполнять опасный код!",
|
||||
"title": "Выполнение кода"
|
||||
},
|
||||
"code_fancy_block": {
|
||||
"label": "[to be translated]:花式代码块",
|
||||
"tip": "[to be translated]:使用更美观的代码块样式,例如 HTML 卡片"
|
||||
},
|
||||
"code_image_tools": {
|
||||
"label": "Включить инструменты предпросмотра",
|
||||
"tip": "Включить инструменты предпросмотра для изображений, сгенерированных из блоков кода (например mermaid)"
|
||||
@ -1741,8 +1745,15 @@
|
||||
"compress_content": "Уменьшить ширину стержня",
|
||||
"compress_content_description": "При включении он ограничит количество слов на строку, уменьшая содержимое, отображаемое на экране.",
|
||||
"default_font": "По умолчанию шрифт",
|
||||
"font_size": "[to be translated]:字体大小",
|
||||
"font_size_description": "[to be translated]:调整字体大小以获得更好的阅读体验 (10-30px)",
|
||||
"font_size_large": "[to be translated]:大",
|
||||
"font_size_medium": "[to be translated]:中",
|
||||
"font_size_small": "[to be translated]:小",
|
||||
"font_title": "Настройки шрифта",
|
||||
"serif_font": "Serif Font",
|
||||
"show_table_of_contents": "[to be translated]:显示目录大纲",
|
||||
"show_table_of_contents_description": "[to be translated]:显示目录大纲侧边栏,方便文档内导航",
|
||||
"title": "показывать"
|
||||
},
|
||||
"editor": {
|
||||
@ -2639,6 +2650,10 @@
|
||||
"url": "URL Joplin",
|
||||
"url_placeholder": "http://127.0.0.1:41184/"
|
||||
},
|
||||
"limit": {
|
||||
"appDataDiskQuota": "Предупреждение о пространстве на диске",
|
||||
"appDataDiskQuotaDescription": "Каталог данных почти заполнен, что может привести к невозможности сохранения новых данных. Сначала создайте резервную копию данных, затем освободите дисковое пространство."
|
||||
},
|
||||
"local": {
|
||||
"autoSync": {
|
||||
"label": "Автоматическое резервное копирование",
|
||||
|
||||
104
src/renderer/src/utils/dataLimit.ts
Normal file
104
src/renderer/src/utils/dataLimit.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import { loggerService } from '@logger'
|
||||
import { AppInfo } from '@renderer/types'
|
||||
import { GB, MB } from '@shared/config/constant'
|
||||
import { t } from 'i18next'
|
||||
|
||||
const logger = loggerService.withContext('useDataLimit')
|
||||
|
||||
const CHECK_INTERVAL_NORMAL = 1000 * 60 * 10 // 10 minutes
|
||||
const CHECK_INTERVAL_WARNING = 1000 * 60 * 1 // 1 minute when warning is active
|
||||
|
||||
let currentInterval: NodeJS.Timeout | null = null
|
||||
let currentToastId: string | null = null
|
||||
|
||||
async function checkAppStorageQuota() {
|
||||
try {
|
||||
const { usage, quota } = await navigator.storage.estimate()
|
||||
if (usage && quota) {
|
||||
const usageInMB = (usage / MB).toFixed(2)
|
||||
const quotaInMB = (quota / MB).toFixed(2)
|
||||
const usagePercentage = (usage / quota) * 100
|
||||
|
||||
logger.info(`App storage quota: Used ${usageInMB} MB / Total ${quotaInMB} MB (${usagePercentage.toFixed(2)}%)`)
|
||||
|
||||
// if usage percentage is greater than 95%,
|
||||
// warn user to clean up app internal data
|
||||
if (usagePercentage >= 95) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Failed to get storage quota:', error as Error)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
async function checkAppDataDiskQuota(appDataPath: string) {
|
||||
try {
|
||||
const diskInfo = await window.api.getDiskInfo(appDataPath)
|
||||
if (!diskInfo) {
|
||||
return false
|
||||
}
|
||||
const { free } = diskInfo
|
||||
logger.info(`App data disk quota: Free ${free} GB`)
|
||||
// if free is less than 1GB, return true
|
||||
return free < 1 * GB
|
||||
} catch (error) {
|
||||
logger.error('Failed to get app data disk quota:', error as Error)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export async function checkDataLimit() {
|
||||
const check = async () => {
|
||||
let isStorageQuotaLow = false
|
||||
let isAppDataDiskQuotaLow = false
|
||||
|
||||
isStorageQuotaLow = await checkAppStorageQuota()
|
||||
|
||||
const appInfo: AppInfo = await window.api.getAppInfo()
|
||||
if (appInfo?.appDataPath) {
|
||||
isAppDataDiskQuotaLow = await checkAppDataDiskQuota(appInfo.appDataPath)
|
||||
}
|
||||
|
||||
const shouldShowWarning = isStorageQuotaLow || isAppDataDiskQuotaLow
|
||||
|
||||
// Show or hide toast based on warning state
|
||||
if (shouldShowWarning && !currentToastId) {
|
||||
// Show persistent toast without close button
|
||||
const toastId = window.toast.warning({
|
||||
title: t('settings.data.limit.appDataDiskQuota'),
|
||||
description: t('settings.data.limit.appDataDiskQuotaDescription'),
|
||||
timeout: 0, // Never auto-dismiss
|
||||
hideCloseButton: true // Hide close button so user cannot dismiss
|
||||
})
|
||||
currentToastId = toastId
|
||||
|
||||
// Switch to warning mode with shorter interval
|
||||
logger.info('Disk space low, switching to 1-minute check interval')
|
||||
if (currentInterval) {
|
||||
clearInterval(currentInterval)
|
||||
}
|
||||
currentInterval = setInterval(check, CHECK_INTERVAL_WARNING)
|
||||
} else if (!shouldShowWarning && currentToastId) {
|
||||
// Dismiss toast when space is recovered
|
||||
window.toast.closeToast(currentToastId)
|
||||
currentToastId = null
|
||||
|
||||
// Switch back to normal mode
|
||||
logger.info('Disk space recovered, switching back to 10-minute check interval')
|
||||
if (currentInterval) {
|
||||
clearInterval(currentInterval)
|
||||
}
|
||||
currentInterval = setInterval(check, CHECK_INTERVAL_NORMAL)
|
||||
}
|
||||
}
|
||||
|
||||
// Initial check
|
||||
check()
|
||||
|
||||
// Set up initial interval (normal mode)
|
||||
if (!currentInterval) {
|
||||
currentInterval = setInterval(check, CHECK_INTERVAL_NORMAL)
|
||||
}
|
||||
}
|
||||
@ -222,6 +222,7 @@ export function uniqueObjectArray<T>(array: T[]): T[] {
|
||||
|
||||
export * from './api'
|
||||
export * from './collection'
|
||||
export * from './dataLimit'
|
||||
export * from './file'
|
||||
export * from './image'
|
||||
export * from './json'
|
||||
|
||||
@ -13150,6 +13150,7 @@ __metadata:
|
||||
axios: "npm:^1.7.3"
|
||||
browser-image-compression: "npm:^2.0.2"
|
||||
chardet: "npm:^2.1.0"
|
||||
check-disk-space: "npm:3.4.0"
|
||||
cheerio: "npm:^1.1.2"
|
||||
chokidar: "npm:^4.0.3"
|
||||
cli-progress: "npm:^3.12.0"
|
||||
@ -14612,6 +14613,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"check-disk-space@npm:3.4.0":
|
||||
version: 3.4.0
|
||||
resolution: "check-disk-space@npm:3.4.0"
|
||||
checksum: 10c0/cc39c91e1337e974fb5069c2fbd9eb92aceca6e35f3da6863a4eada58f15c1bf6970055bffed1e41c15cde1fd0ad2580bb99bef8275791ed56d69947f8657aa5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"check-error@npm:^2.1.1":
|
||||
version: 2.1.1
|
||||
resolution: "check-error@npm:2.1.1"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user