858 lines
32 KiB
TypeScript
858 lines
32 KiB
TypeScript
import { invoke } from '@tauri-apps/api'
|
|
import { emit, listen, TauriEvent } from '@tauri-apps/api/event'
|
|
import { relaunch } from '@tauri-apps/api/process'
|
|
import { checkUpdate, installUpdate } from '@tauri-apps/api/updater'
|
|
import { semverCompare } from '~/libs/utils'
|
|
import i18n from '~/locales'
|
|
import dayjs from 'dayjs'
|
|
import { atomWithStore } from 'jotai-zustand'
|
|
import { createStore } from 'zustand/vanilla'
|
|
|
|
import DOMPurify from '../components/libs/dompurify'
|
|
import {
|
|
availableVersionBody,
|
|
availableVersionDate,
|
|
availableVersionDateISO,
|
|
availableVersionNumber,
|
|
showRestartAfterUpdate,
|
|
showUpdateAppIsLatest,
|
|
showUpdateAvailable,
|
|
showUpdateChecking,
|
|
showUpdateError,
|
|
showUpdateErrorPermissionDenied,
|
|
showUpdateInstalling,
|
|
} from './signalStore'
|
|
|
|
type Settings = {
|
|
appLastUpdateVersion: string
|
|
appLastUpdateDate: string
|
|
appDataDir: string
|
|
isAppReady: boolean
|
|
isClipNotesHoverCardsEnabled: boolean
|
|
clipNotesHoverCardsDelayMS: number
|
|
clipNotesMaxWidth: number
|
|
clipNotesMaxHeight: number
|
|
isHistoryEnabled: boolean
|
|
historyExclusionList: string
|
|
historyExclusionAppList: string
|
|
historyDetectLanguagesEnabledList: string[]
|
|
appToursCompletedList: string[]
|
|
appToursSkippedList: string[]
|
|
historyDetectLanguagesPrioritizedList: string[]
|
|
isHistoryDetectLanguageEnabled: boolean
|
|
isExclusionListEnabled: boolean
|
|
isExclusionAppListEnabled: boolean
|
|
historyDetectLanguageMinLines: number
|
|
isAutoMaskWordsListEnabled: boolean
|
|
isAutoClearSettingsEnabled: boolean
|
|
autoClearSettingsDuration: number
|
|
autoClearSettingsDurationType: string
|
|
autoMaskWordsList: string
|
|
isHistoryAutoUpdateOnCaputureEnabled: boolean
|
|
isHistoryAutoTrimOnCaputureEnabled: boolean
|
|
copyPasteDelay: number
|
|
copyPasteSequencePinnedDelay: number
|
|
copyPasteSequenceIsReversOrder: boolean
|
|
hotKeysShowHideMainAppWindow: string
|
|
hotKeysShowHideQuickPasteWindow: string
|
|
isHideMacOSDockIcon: boolean
|
|
isAutoCloseOnCopyPaste: boolean
|
|
isAutoPreviewLinkCardsEnabled: boolean
|
|
isAutoGenerateLinkCardsEnabled: boolean
|
|
isAutoFavoriteOnDoubleCopyEnabled: boolean
|
|
isSearchNameOrLabelOnly: boolean
|
|
isShowCollectionNameOnNavBar: boolean
|
|
isShowDisabledCollectionsOnNavBarMenu: boolean
|
|
isSkipAutoStartPrompt: boolean
|
|
isHideCollectionsOnNavBar: boolean
|
|
isShowNavBarItemsOnHoverOnly: boolean
|
|
isKeepMainWindowClosedOnRestartEnabled: boolean
|
|
pasteSequenceEachSeparator: string
|
|
userSelectedLanguage: string
|
|
isFirstRun: boolean
|
|
isFirstRunAfterUpdate: boolean
|
|
isIdleScreenAutoLockEnabled: boolean
|
|
idleScreenAutoLockTimeInMinutes: number | null
|
|
isShowHistoryCaptureOnLockedScreen: boolean
|
|
screenLockPassCode: string | null
|
|
screenLockPassCodeLength: number
|
|
screenLockRecoveryPasswordMasked: string | null
|
|
isAppLocked: boolean
|
|
isScreenLockPassCodeRequireOnStart: boolean
|
|
clipTextMinLength: number
|
|
clipTextMaxLength: number
|
|
}
|
|
|
|
type Constants = {
|
|
APP_DETECT_LANGUAGES_SUPPORTED: string[]
|
|
}
|
|
|
|
export interface SettingsStoreState {
|
|
setIsHistoryEnabled: (isHistoryEnabled: boolean) => void
|
|
setIsHistoryAutoUpdateOnCaputureEnabled: (
|
|
isHistoryAutoUpdateOnCaputureEnabled: boolean
|
|
) => void
|
|
setIsHistoryAutoTrimOnCaputureEnabled: (
|
|
isHistoryAutoTrimOnCaputureEnabled: boolean
|
|
) => void
|
|
setIsFirstRun: (isFirstRun: boolean) => void
|
|
setIsFirstRunAfterUpdate: (isFirstRunAfterUpdate: boolean) => void
|
|
setCopyPasteDelay: (delay: number) => void
|
|
setCopyPasteSequencePinnedDelay: (delay: number) => void
|
|
setCopyPasteSequenceIsReversOrder: (isReversOrder: boolean) => void
|
|
setPasteSequenceEachSeparator: (separator: string) => void
|
|
setHistoryDetectLanguageMinLines: (lines: number) => void
|
|
setHistoryExclusionList: (text: string) => void
|
|
setHistoryExclusionAppList: (text: string) => void
|
|
addToHistoryExclusionAppList: (text: string) => void
|
|
setIsHistoryDetectLanguageEnabled: (isEnabled: boolean) => void
|
|
setIsExclusionListEnabled: (isEnabled: boolean) => void
|
|
setIsExclusionAppListEnabled: (isEnabled: boolean) => void
|
|
setIsAutoClearSettingsEnabled: (isEnabled: boolean) => void
|
|
setAutoClearSettingsDuration: (duration: number) => void
|
|
setAutoClearSettingsDurationType: (type: string) => void
|
|
CONST: Constants
|
|
setAppLastUpdateVersion: (appLastUpdateVersion: string) => void
|
|
setAppLastUpdateDate: (appLastUpdateDate: string) => void
|
|
setIsAutoMaskWordsListEnabled: (isEnabled: boolean) => void
|
|
setAutoMaskWordsList: (text: string) => void
|
|
setHistoryDetectLanguagesEnabledList: (words: string[]) => void
|
|
setAppToursCompletedList: (words: string[]) => void
|
|
setAppToursSkippedList: (words: string[]) => void
|
|
setHistoryDetectLanguagesPrioritizedList: (words: string[]) => void
|
|
setAppDataDir: (appDataDir: string) => void
|
|
setIsAutoCloseOnCopyPaste: (isEnabled: boolean) => void
|
|
setClipNotesHoverCardsDelayMS: (delay: number) => void
|
|
setClipNotesMaxWidth: (width: number) => void
|
|
setClipNotesMaxHeight: (height: number) => void
|
|
setIsClipNotesHoverCardsEnabled: (isEnabled: boolean) => void
|
|
setIsAutoPreviewLinkCardsEnabled: (isEnabled: boolean) => void
|
|
setIsAutoGenerateLinkCardsEnabled: (isEnabled: boolean) => void
|
|
setIsAutoFavoriteOnDoubleCopyEnabled: (isEnabled: boolean) => void
|
|
setIsSearchNameOrLabelOnly: (isEnabled: boolean) => void
|
|
initConstants: (CONST: Constants) => void
|
|
setIsShowCollectionNameOnNavBar: (isEnabled: boolean) => void
|
|
setIsShowDisabledCollectionsOnNavBarMenu: (isEnabled: boolean) => void
|
|
setIsSkipAutoStartPrompt: (isEnabled: boolean) => void
|
|
setUserSelectedLanguage: (language: string) => void
|
|
setIsIdleScreenAutoLockEnabled: (isEnabled: boolean) => void
|
|
setIdleScreenAutoLockTimeInMinutes: (time: number | null) => void
|
|
setIsShowHistoryCaptureOnLockedScreen: (isEnabled: boolean) => void
|
|
setScreenLockPassCode: (passCode: string | null) => void
|
|
setScreenLockPassCodeLength: (length: number) => void
|
|
setScreenLockResetTempPassCode: (tempPassCode: string | null) => void
|
|
setScreenLockRecoveryPasswordMasked: (backupPasswordMasked: string | null) => void
|
|
setIsAppLocked: (isLocked: boolean) => void
|
|
setIsScreenLockPassCodeRequireOnStart: (isRequire: boolean) => void
|
|
setIsHideMacOSDockIcon: (isHideMacOSDockIcon: boolean) => void
|
|
setHotKeysShowHideMainAppWindow: (hotKeysShowHideMainAppWindow: string) => void
|
|
setHotKeysShowHideQuickPasteWindow: (hotKeysShowHideQuickPasteWindow: string) => void
|
|
setIsKeepMainWindowClosedOnRestartEnabled: (isEnabled: boolean) => void
|
|
setIsHideCollectionsOnNavBar: (isEnabled: boolean) => void
|
|
setIsShowNavBarItemsOnHoverOnly: (isEnabled: boolean) => void
|
|
hashPassword: (pass: string) => Promise<string>
|
|
isNotTourCompletedOrSkipped: (tourName: string) => boolean
|
|
verifyPassword: (pass: string, hash: string) => Promise<boolean>
|
|
storePassword: (name: string, pass: string) => Promise<string>
|
|
getStoredPassword: (name: string) => Promise<string | null>
|
|
verifyStoredPassword: (name: string, pass: string) => Promise<string>
|
|
deleteStoredPassword: (name: string) => Promise<boolean>
|
|
updateSetting: (name: string, value: string | boolean | number | null) => void
|
|
checkForUpdate: (isManualCheck?: boolean) => void
|
|
resetCheckForUpdate: () => void
|
|
shouldSkipVersionCheck: (newVersion: string, isManualCheck?: boolean) => boolean
|
|
setUpdaterRemindLater: (isReset?: boolean) => void
|
|
setUpdaterSkipVersion: (skipVersion: string | null) => void
|
|
installUpdate: () => void
|
|
syncStateUpdate: (name: string, value: any) => void
|
|
relaunchApp: () => void
|
|
initSettings: (settings: Settings) => void
|
|
setClipTextMinLength: (width: number) => void
|
|
setClipTextMaxLength: (height: number) => void
|
|
}
|
|
|
|
const initialState: SettingsStoreState & Settings = {
|
|
appLastUpdateVersion: '0.0.1',
|
|
appLastUpdateDate: '',
|
|
isAppReady: false,
|
|
appDataDir: '',
|
|
isHistoryEnabled: true,
|
|
isFirstRun: true,
|
|
historyDetectLanguagesEnabledList: [],
|
|
appToursCompletedList: [],
|
|
appToursSkippedList: [],
|
|
historyDetectLanguagesPrioritizedList: [],
|
|
historyExclusionList: '',
|
|
historyExclusionAppList: '',
|
|
isHideCollectionsOnNavBar: false,
|
|
isShowNavBarItemsOnHoverOnly: false,
|
|
isKeepMainWindowClosedOnRestartEnabled: false,
|
|
isExclusionListEnabled: false,
|
|
isExclusionAppListEnabled: false,
|
|
isAutoClearSettingsEnabled: false,
|
|
isAutoMaskWordsListEnabled: false,
|
|
isHideMacOSDockIcon: false,
|
|
isNotTourCompletedOrSkipped: () => false,
|
|
hotKeysShowHideMainAppWindow: '',
|
|
hotKeysShowHideQuickPasteWindow: '',
|
|
autoMaskWordsList: '',
|
|
isHistoryDetectLanguageEnabled: true,
|
|
historyDetectLanguageMinLines: 3,
|
|
autoClearSettingsDuration: 1,
|
|
autoClearSettingsDurationType: 'months',
|
|
copyPasteDelay: 0,
|
|
copyPasteSequencePinnedDelay: 3,
|
|
copyPasteSequenceIsReversOrder: false,
|
|
pasteSequenceEachSeparator: '',
|
|
isSearchNameOrLabelOnly: true,
|
|
isAutoCloseOnCopyPaste: false,
|
|
isAutoPreviewLinkCardsEnabled: true,
|
|
isAutoGenerateLinkCardsEnabled: true,
|
|
isAutoFavoriteOnDoubleCopyEnabled: true,
|
|
isShowCollectionNameOnNavBar: true,
|
|
isShowDisabledCollectionsOnNavBarMenu: true,
|
|
isClipNotesHoverCardsEnabled: true,
|
|
clipNotesHoverCardsDelayMS: 2000,
|
|
clipNotesMaxWidth: 220,
|
|
clipNotesMaxHeight: 120,
|
|
isSkipAutoStartPrompt: false,
|
|
userSelectedLanguage: '',
|
|
isHistoryAutoUpdateOnCaputureEnabled: true,
|
|
isHistoryAutoTrimOnCaputureEnabled: true,
|
|
isIdleScreenAutoLockEnabled: false,
|
|
idleScreenAutoLockTimeInMinutes: null,
|
|
isShowHistoryCaptureOnLockedScreen: false,
|
|
screenLockPassCode: null,
|
|
screenLockPassCodeLength: 0,
|
|
screenLockRecoveryPasswordMasked: null,
|
|
isAppLocked: false,
|
|
isScreenLockPassCodeRequireOnStart: false,
|
|
isFirstRunAfterUpdate: false,
|
|
clipTextMinLength: 0,
|
|
clipTextMaxLength: 5000,
|
|
CONST: {
|
|
APP_DETECT_LANGUAGES_SUPPORTED: [],
|
|
},
|
|
setClipNotesMaxWidth: () => {},
|
|
setClipNotesMaxHeight: () => {},
|
|
setIsHistoryEnabled: () => {},
|
|
setCopyPasteDelay: () => {},
|
|
setCopyPasteSequencePinnedDelay: () => {},
|
|
setCopyPasteSequenceIsReversOrder: () => {},
|
|
setPasteSequenceEachSeparator: () => {},
|
|
setIsExclusionListEnabled: () => {},
|
|
setHistoryExclusionAppList: () => {},
|
|
setIsExclusionAppListEnabled: () => {},
|
|
setHistoryDetectLanguageMinLines: () => {},
|
|
setAutoClearSettingsDuration: () => {},
|
|
setAutoClearSettingsDurationType: () => {},
|
|
setIsHistoryDetectLanguageEnabled: () => {},
|
|
setIsHideMacOSDockIcon: () => {},
|
|
setHotKeysShowHideMainAppWindow: () => {},
|
|
setHotKeysShowHideQuickPasteWindow: () => {},
|
|
setHistoryExclusionList: () => {},
|
|
setIsHistoryAutoUpdateOnCaputureEnabled: () => {},
|
|
setIsHistoryAutoTrimOnCaputureEnabled: () => {},
|
|
addToHistoryExclusionAppList: () => {},
|
|
setHistoryDetectLanguagesEnabledList: () => {},
|
|
setAppToursCompletedList: () => {},
|
|
setAppToursSkippedList: () => {},
|
|
setHistoryDetectLanguagesPrioritizedList: () => {},
|
|
setIsAutoClearSettingsEnabled: () => {},
|
|
setIsAutoMaskWordsListEnabled: () => {},
|
|
setIsAutoCloseOnCopyPaste: () => {},
|
|
setIsAutoPreviewLinkCardsEnabled: () => {},
|
|
setIsAutoGenerateLinkCardsEnabled: () => {},
|
|
setIsAutoFavoriteOnDoubleCopyEnabled: () => {},
|
|
setIsSearchNameOrLabelOnly: () => {},
|
|
setAutoMaskWordsList: () => {},
|
|
setIsShowCollectionNameOnNavBar: () => {},
|
|
setIsShowDisabledCollectionsOnNavBarMenu: () => {},
|
|
setIsSkipAutoStartPrompt: () => {},
|
|
setIdleScreenAutoLockTimeInMinutes: () => {},
|
|
setIsIdleScreenAutoLockEnabled: () => {},
|
|
setIsShowHistoryCaptureOnLockedScreen: () => {},
|
|
setScreenLockPassCode: () => {},
|
|
setScreenLockPassCodeLength: () => {},
|
|
setScreenLockResetTempPassCode: () => {},
|
|
setScreenLockRecoveryPasswordMasked: () => {},
|
|
setIsAppLocked: () => {},
|
|
setClipNotesHoverCardsDelayMS: () => {},
|
|
setIsClipNotesHoverCardsEnabled: () => {},
|
|
setIsScreenLockPassCodeRequireOnStart: () => {},
|
|
setIsFirstRunAfterUpdate: () => {},
|
|
setIsKeepMainWindowClosedOnRestartEnabled: () => {},
|
|
setIsHideCollectionsOnNavBar: () => {},
|
|
setIsShowNavBarItemsOnHoverOnly: () => {},
|
|
setClipTextMinLength: () => {},
|
|
setClipTextMaxLength: () => {},
|
|
initConstants: () => {},
|
|
setAppDataDir: () => {},
|
|
updateSetting: () => {},
|
|
setIsFirstRun: () => {},
|
|
setAppLastUpdateVersion: () => {},
|
|
setAppLastUpdateDate: () => {},
|
|
setUserSelectedLanguage: () => {},
|
|
initSettings: () => {},
|
|
checkForUpdate: () => {},
|
|
resetCheckForUpdate: () => {},
|
|
shouldSkipVersionCheck: () => false,
|
|
setUpdaterRemindLater: () => {},
|
|
setUpdaterSkipVersion: () => {},
|
|
relaunchApp: () => {
|
|
relaunch()
|
|
},
|
|
installUpdate: () => {},
|
|
hashPassword: (password: string): Promise<string> =>
|
|
invoke('hash_password', { password }),
|
|
storePassword: (name: string, password: string): Promise<string> =>
|
|
invoke('store_os_password', { name, password }),
|
|
getStoredPassword: (name: string): Promise<string | null> => {
|
|
try {
|
|
return invoke('get_stored_os_password', { name })
|
|
} catch (e) {
|
|
return Promise.resolve(null)
|
|
}
|
|
},
|
|
syncStateUpdate: () => {},
|
|
verifyStoredPassword: (name: string, password: string): Promise<string> =>
|
|
invoke('verify_os_password', { name, password }),
|
|
deleteStoredPassword: (name: string): Promise<boolean> =>
|
|
invoke('delete_os_password', { name }),
|
|
verifyPassword: (password: string, hash: string): Promise<boolean> =>
|
|
invoke('verify_password', { password, hash }),
|
|
}
|
|
|
|
export const settingsStore = createStore<SettingsStoreState & Settings>()((set, get) => ({
|
|
...initialState,
|
|
syncStateUpdate: (setting: string, value: string | boolean | number | null) => {
|
|
emit('settings-store-sync', { setting, value })
|
|
},
|
|
|
|
updateSetting: async (name: string, value: string | boolean | number | null) => {
|
|
let settingType
|
|
if (typeof value === 'boolean') {
|
|
settingType = { valueBool: value }
|
|
} else if (typeof value === 'string') {
|
|
settingType = { valueText: value }
|
|
} else if (typeof value === 'number') {
|
|
settingType = { valueInt: value }
|
|
} else {
|
|
settingType = { valueInt: null, valueText: null, valueBool: null }
|
|
}
|
|
|
|
try {
|
|
await invoke('update_setting', {
|
|
setting: {
|
|
name,
|
|
...settingType,
|
|
},
|
|
})
|
|
|
|
if (
|
|
name === 'isHistoryEnabled' ||
|
|
name === 'userSelectedLanguage' ||
|
|
name === 'isAppLocked'
|
|
) {
|
|
invoke('build_system_menu')
|
|
}
|
|
|
|
if (name === 'historyDetectLanguagesEnabledList' && typeof value === 'string') {
|
|
return set(() => ({
|
|
historyDetectLanguagesEnabledList: value.split(','),
|
|
}))
|
|
}
|
|
|
|
if (name === 'appToursCompletedList' && typeof value === 'string') {
|
|
return set(() => ({
|
|
appToursCompletedList: value.split(','),
|
|
}))
|
|
}
|
|
|
|
if (name === 'appToursSkippedList' && typeof value === 'string') {
|
|
return set(() => ({
|
|
appToursSkippedList: value.split(','),
|
|
}))
|
|
}
|
|
|
|
if (name === 'historyDetectLanguagesPrioritizedList' && typeof value === 'string') {
|
|
return set(() => ({
|
|
historyDetectLanguagesPrioritizedList: value.split(','),
|
|
}))
|
|
}
|
|
|
|
return set(() => ({ [name]: value }))
|
|
} catch (e) {
|
|
console.error(e)
|
|
}
|
|
},
|
|
setIsHistoryAutoTrimOnCaputureEnabled: async (
|
|
isHistoryAutoTrimOnCaputureEnabled: boolean
|
|
) => {
|
|
return get().updateSetting(
|
|
'isHistoryAutoTrimOnCaputureEnabled',
|
|
isHistoryAutoTrimOnCaputureEnabled
|
|
)
|
|
},
|
|
setIsHistoryAutoUpdateOnCaputureEnabled: async (
|
|
isHistoryAutoUpdateOnCaputureEnabled: boolean
|
|
) => {
|
|
get().syncStateUpdate(
|
|
'isHistoryAutoUpdateOnCaputureEnabled',
|
|
isHistoryAutoUpdateOnCaputureEnabled
|
|
)
|
|
return get().updateSetting(
|
|
'isHistoryAutoUpdateOnCaputureEnabled',
|
|
isHistoryAutoUpdateOnCaputureEnabled
|
|
)
|
|
},
|
|
setIsHistoryEnabled: async (isHistoryEnabled: boolean) => {
|
|
get().syncStateUpdate('isHistoryEnabled', isHistoryEnabled)
|
|
return get().updateSetting('isHistoryEnabled', isHistoryEnabled)
|
|
},
|
|
setIsHistoryDetectLanguageEnabled: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isHistoryDetectLanguageEnabled', isEnabled)
|
|
},
|
|
setHistoryDetectLanguageMinLines: async (lines: number) => {
|
|
return get().updateSetting('historyDetectLanguageMinLines', lines)
|
|
},
|
|
setHistoryExclusionList: async (text: string) => {
|
|
return get().updateSetting('historyExclusionList', text)
|
|
},
|
|
setHistoryExclusionAppList: async (text: string) => {
|
|
return get().updateSetting('historyExclusionAppList', text)
|
|
},
|
|
addToHistoryExclusionAppList: async (text: string) => {
|
|
const { historyExclusionAppList } = get()
|
|
const list = historyExclusionAppList.split('\n').filter(Boolean)
|
|
list.push(text)
|
|
const newList = Array.from(new Set(list)).join('\n')
|
|
return get().updateSetting('historyExclusionAppList', newList)
|
|
},
|
|
setAutoMaskWordsList: async (text: string) => {
|
|
return get().updateSetting('autoMaskWordsList', text)
|
|
},
|
|
setUserSelectedLanguage: async (text: string) => {
|
|
get().syncStateUpdate('userSelectedLanguage', text)
|
|
return get().updateSetting('userSelectedLanguage', text)
|
|
},
|
|
setAutoClearSettingsDuration: async (duration: number) => {
|
|
return get().updateSetting('autoClearSettingsDuration', duration)
|
|
},
|
|
setAutoClearSettingsDurationType: async (type: string) => {
|
|
return get().updateSetting('autoClearSettingsDurationType', type)
|
|
},
|
|
setIsAutoMaskWordsListEnabled: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isAutoMaskWordsListEnabled', isEnabled)
|
|
},
|
|
setIsAutoCloseOnCopyPaste: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isAutoCloseOnCopyPaste', isEnabled)
|
|
},
|
|
setIsSearchNameOrLabelOnly: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isSearchNameOrLabelOnly', isEnabled)
|
|
},
|
|
setIsAutoClearSettingsEnabled: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isAutoClearSettingsEnabled', isEnabled)
|
|
},
|
|
setIsAutoPreviewLinkCardsEnabled: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isAutoPreviewLinkCardsEnabled', isEnabled)
|
|
},
|
|
setIsAutoGenerateLinkCardsEnabled: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isAutoGenerateLinkCardsEnabled', isEnabled)
|
|
},
|
|
setIsAutoFavoriteOnDoubleCopyEnabled: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isAutoFavoriteOnDoubleCopyEnabled', isEnabled)
|
|
},
|
|
setIsExclusionListEnabled: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isExclusionListEnabled', isEnabled)
|
|
},
|
|
setIsExclusionAppListEnabled: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isExclusionAppListEnabled', isEnabled)
|
|
},
|
|
setIsShowCollectionNameOnNavBar: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isShowCollectionNameOnNavBar', isEnabled)
|
|
},
|
|
setIsSkipAutoStartPrompt: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isSkipAutoStartPrompt', isEnabled)
|
|
},
|
|
setIsShowDisabledCollectionsOnNavBarMenu: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isShowDisabledCollectionsOnNavBarMenu', isEnabled)
|
|
},
|
|
setHistoryDetectLanguagesEnabledList: async (list: string[]) => {
|
|
return get().updateSetting(
|
|
'historyDetectLanguagesEnabledList',
|
|
list.filter(Boolean).join()
|
|
)
|
|
},
|
|
setAppToursCompletedList: async (list: string[]) => {
|
|
return get().updateSetting('appToursCompletedList', list.filter(Boolean).join())
|
|
},
|
|
setAppToursSkippedList: async (list: string[]) => {
|
|
return get().updateSetting('appToursSkippedList', list.filter(Boolean).join())
|
|
},
|
|
setHistoryDetectLanguagesPrioritizedList: async (list: string[]) => {
|
|
return get().updateSetting(
|
|
'historyDetectLanguagesPrioritizedList',
|
|
list.filter(Boolean).join()
|
|
)
|
|
},
|
|
setIsClipNotesHoverCardsEnabled: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isClipNotesHoverCardsEnabled', isEnabled)
|
|
},
|
|
setClipNotesHoverCardsDelayMS: async (delay: number) => {
|
|
return get().updateSetting('clipNotesHoverCardsDelayMS', delay)
|
|
},
|
|
setClipNotesMaxHeight: async (height: number) => {
|
|
return get().updateSetting('clipNotesMaxHeight', height)
|
|
},
|
|
setClipNotesMaxWidth: async (width: number) => {
|
|
return get().updateSetting('clipNotesMaxWidth', width)
|
|
},
|
|
setCopyPasteDelay: async (delay: number) => {
|
|
get().syncStateUpdate('copyPasteDelay', delay)
|
|
return get().updateSetting('copyPasteDelay', delay)
|
|
},
|
|
setCopyPasteSequencePinnedDelay: async (delay: number) => {
|
|
get().syncStateUpdate('copyPasteSequencePinnedDelay', delay)
|
|
return get().updateSetting('copyPasteSequencePinnedDelay', delay)
|
|
},
|
|
setCopyPasteSequenceIsReversOrder: async (isReversOrder: boolean) => {
|
|
get().syncStateUpdate('copyPasteSequenceIsReversOrder', isReversOrder)
|
|
return get().updateSetting('copyPasteSequenceIsReversOrder', isReversOrder)
|
|
},
|
|
setPasteSequenceEachSeparator: async (separator: string) => {
|
|
get().syncStateUpdate('pasteSequenceEachSeparator', separator)
|
|
return get().updateSetting('pasteSequenceEachSeparator', separator)
|
|
},
|
|
setIsIdleScreenAutoLockEnabled: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isIdleScreenAutoLockEnabled', isEnabled)
|
|
},
|
|
setIdleScreenAutoLockTimeInMinutes: async (time: number | null) => {
|
|
return get().updateSetting('idleScreenAutoLockTimeInMinutes', time)
|
|
},
|
|
setIsShowHistoryCaptureOnLockedScreen: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isShowHistoryCaptureOnLockedScreen', isEnabled)
|
|
},
|
|
setScreenLockPassCode: async (passCode: string | null) => {
|
|
get().syncStateUpdate('screenLockPassCode', passCode)
|
|
return get().updateSetting('screenLockPassCode', passCode ? passCode : null)
|
|
},
|
|
setScreenLockPassCodeLength: async (length: number) => {
|
|
return get().updateSetting('screenLockPassCodeLength', length)
|
|
},
|
|
setScreenLockRecoveryPasswordMasked: async (backupPasswordMasked: string | null) => {
|
|
return get().updateSetting('screenLockRecoveryPasswordMasked', backupPasswordMasked)
|
|
},
|
|
setIsAppLocked: async (isLocked: boolean) => {
|
|
return get().updateSetting('isAppLocked', isLocked)
|
|
},
|
|
setIsScreenLockPassCodeRequireOnStart: async (isRequire: boolean) => {
|
|
return get().updateSetting('isScreenLockPassCodeRequireOnStart', isRequire)
|
|
},
|
|
setIsFirstRunAfterUpdate: async (isFirstRunAfterUpdate: boolean) => {
|
|
return get().updateSetting('isFirstRunAfterUpdate', isFirstRunAfterUpdate)
|
|
},
|
|
setIsFirstRun: (isFirstRun: boolean) => {
|
|
return get().updateSetting('isFirstRun', isFirstRun)
|
|
},
|
|
setIsHideMacOSDockIcon: async (isHideMacOSDockIcon: boolean) => {
|
|
return get().updateSetting('isHideMacOSDockIcon', isHideMacOSDockIcon)
|
|
},
|
|
setHotKeysShowHideMainAppWindow: async (hotKeysShowHideMainAppWindow: string) => {
|
|
return get().updateSetting(
|
|
'hotKeysShowHideMainAppWindow',
|
|
hotKeysShowHideMainAppWindow
|
|
)
|
|
},
|
|
setIsKeepMainWindowClosedOnRestartEnabled: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isKeepMainWindowClosedOnRestartEnabled', isEnabled)
|
|
},
|
|
setIsHideCollectionsOnNavBar: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isHideCollectionsOnNavBar', isEnabled)
|
|
},
|
|
setIsShowNavBarItemsOnHoverOnly: async (isEnabled: boolean) => {
|
|
return get().updateSetting('isShowNavBarItemsOnHoverOnly', isEnabled)
|
|
},
|
|
setHotKeysShowHideQuickPasteWindow: async (hotKeysShowHideQuickPasteWindow: string) => {
|
|
return get().updateSetting(
|
|
'hotKeysShowHideQuickPasteWindow',
|
|
hotKeysShowHideQuickPasteWindow
|
|
)
|
|
},
|
|
setClipTextMinLength: async (length: number) => {
|
|
return get().updateSetting('clipTextMinLength', length)
|
|
},
|
|
setClipTextMaxLength: async (length: number) => {
|
|
return get().updateSetting('clipTextMaxLength', length)
|
|
},
|
|
isNotTourCompletedOrSkipped: (tourName: string) => {
|
|
const { appToursCompletedList, appToursSkippedList } = get()
|
|
return (
|
|
!appToursCompletedList.includes(tourName) && !appToursSkippedList.includes(tourName)
|
|
)
|
|
},
|
|
installUpdate: async () => {
|
|
showUpdateInstalling.value = true
|
|
showUpdateError.value = false
|
|
showUpdateErrorPermissionDenied.value = false
|
|
|
|
try {
|
|
await checkUpdate()
|
|
await installUpdate()
|
|
showUpdateInstalling.value = false
|
|
showRestartAfterUpdate.value = true
|
|
get().setIsFirstRunAfterUpdate(true)
|
|
if (availableVersionNumber.value) {
|
|
get().setAppLastUpdateVersion(availableVersionNumber.value)
|
|
}
|
|
if (availableVersionDateISO.value) {
|
|
get().setAppLastUpdateDate(availableVersionDateISO.value)
|
|
}
|
|
|
|
setTimeout(() => {
|
|
relaunch()
|
|
}, 600)
|
|
} catch (e) {
|
|
console.error('Install Update Error:', e)
|
|
const { message } = e as Error
|
|
if (
|
|
message?.toLocaleLowerCase().includes('permission') ||
|
|
message?.toLocaleLowerCase().includes('denied')
|
|
) {
|
|
showUpdateErrorPermissionDenied.value = true
|
|
}
|
|
showUpdateInstalling.value = false
|
|
showUpdateError.value = true
|
|
}
|
|
},
|
|
checkForUpdate: async (isManualCheck?: boolean) => {
|
|
showUpdateChecking.value = true
|
|
try {
|
|
const { shouldUpdate, manifest } = await checkUpdate()
|
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
|
|
if (
|
|
shouldUpdate &&
|
|
manifest?.version &&
|
|
!get().shouldSkipVersionCheck(manifest?.version, isManualCheck)
|
|
) {
|
|
availableVersionNumber.value = manifest?.version ?? null
|
|
if (manifest?.body && window['markdown']) {
|
|
// @ts-expect-error
|
|
window['markdown'].ready.then(markdown => {
|
|
try {
|
|
const html = markdown.parse(manifest?.body)
|
|
availableVersionBody.value = DOMPurify.sanitize(html as string, {
|
|
USE_PROFILES: { html: true },
|
|
})
|
|
} catch (e) {
|
|
if (import.meta.env.TAURI_DEBUG) {
|
|
console.error('Markdown Parse Error:', e)
|
|
}
|
|
availableVersionBody.value = null
|
|
}
|
|
})
|
|
} else {
|
|
availableVersionBody.value = null
|
|
}
|
|
|
|
if (manifest?.date) {
|
|
const versionDate = manifest?.date.split(' ')[0] ?? null
|
|
availableVersionDate.value = dayjs(versionDate).format('DD MMMM, YYYY')
|
|
availableVersionDateISO.value = dayjs(versionDate).format('YYYY-MM-DD')
|
|
}
|
|
showUpdateAvailable.value = true
|
|
showUpdateChecking.value = false
|
|
} else {
|
|
if (isManualCheck) {
|
|
showUpdateAppIsLatest.value = true
|
|
setTimeout(() => {
|
|
showUpdateAppIsLatest.value = false
|
|
showUpdateChecking.value = false
|
|
}, 3000)
|
|
} else {
|
|
showUpdateChecking.value = false
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error('Check Update Error:', e)
|
|
if (isManualCheck) {
|
|
showUpdateChecking.value = false
|
|
showUpdateAppIsLatest.value = true
|
|
setTimeout(() => {
|
|
showUpdateAppIsLatest.value = false
|
|
showUpdateChecking.value = false
|
|
}, 3000)
|
|
} else {
|
|
showUpdateChecking.value = false
|
|
}
|
|
}
|
|
if (isManualCheck) {
|
|
get().setUpdaterRemindLater(true)
|
|
get().setUpdaterSkipVersion(null)
|
|
}
|
|
},
|
|
shouldSkipVersionCheck: (newVersion: string, isManualCheck?: boolean) => {
|
|
if (isManualCheck) {
|
|
return false
|
|
}
|
|
|
|
const remindLater = localStorage.getItem('updaterRemindLater')
|
|
|
|
if (remindLater && dayjs().isBefore(remindLater)) {
|
|
return true
|
|
}
|
|
|
|
const skipVersion = localStorage.getItem('updaterSkipVersion')
|
|
|
|
return Boolean(
|
|
skipVersion &&
|
|
(skipVersion === newVersion || semverCompare(skipVersion, newVersion) >= 0)
|
|
)
|
|
},
|
|
setUpdaterRemindLater: (isReset?: boolean) => {
|
|
if (isReset) {
|
|
localStorage.removeItem('updaterRemindLater')
|
|
return
|
|
}
|
|
localStorage.setItem('updaterRemindLater', dayjs().add(3, 'day').format('YYYY-MM-DD'))
|
|
get().resetCheckForUpdate()
|
|
},
|
|
setUpdaterSkipVersion: (skipVersion: string | null) => {
|
|
if (skipVersion === null) {
|
|
localStorage.removeItem('updaterSkipVersion')
|
|
return
|
|
}
|
|
localStorage.setItem('updaterSkipVersion', skipVersion)
|
|
get().resetCheckForUpdate()
|
|
},
|
|
resetCheckForUpdate: () => {
|
|
showUpdateAvailable.value = false
|
|
showUpdateAppIsLatest.value = false
|
|
showRestartAfterUpdate.value = false
|
|
showUpdateInstalling.value = false
|
|
showUpdateError.value = false
|
|
availableVersionNumber.value = null
|
|
availableVersionBody.value = null
|
|
availableVersionDate.value = null
|
|
availableVersionDateISO.value = null
|
|
},
|
|
initConstants: (CONST: Constants) => set(() => ({ CONST })),
|
|
setAppDataDir: (appDataDir: string) =>
|
|
set(() => ({
|
|
appDataDir,
|
|
})),
|
|
setAppLastUpdateVersion: (appLastUpdateVersion: string) => {
|
|
return get().updateSetting('appLastUpdateVersion', appLastUpdateVersion)
|
|
},
|
|
setAppLastUpdateDate: (appLastUpdateDate: string) => {
|
|
return get().updateSetting('appLastUpdateDate', appLastUpdateDate)
|
|
},
|
|
initSettings: (settings: Settings) => {
|
|
const newInitSettings = Object.keys(initialState).reduce(
|
|
(acc: Settings, key: string) => {
|
|
if (
|
|
typeof settings[key as keyof Settings] !== 'undefined' &&
|
|
settings[key as keyof Settings] !== null
|
|
) {
|
|
// @ts-expect-error
|
|
acc[key as keyof Settings] = settings[key as keyof Settings]
|
|
}
|
|
return acc
|
|
},
|
|
{} as Settings
|
|
)
|
|
|
|
set(prev => ({
|
|
...prev,
|
|
...newInitSettings,
|
|
}))
|
|
},
|
|
}))
|
|
|
|
export const listenToSettingsStoreEvents = listen('settings-store-sync', async event => {
|
|
const { payload } = event
|
|
const { setting, value } = payload as {
|
|
setting: string
|
|
value: string | boolean | number | null
|
|
}
|
|
if (
|
|
(window.isHistoryWindow && event.windowLabel !== 'history') ||
|
|
(window.isMainWindow && event.windowLabel !== 'main')
|
|
) {
|
|
if (
|
|
setting === 'userSelectedLanguage' &&
|
|
settingsStore.getState().userSelectedLanguage !== value &&
|
|
typeof value === 'string'
|
|
) {
|
|
i18n.changeLanguage(value)
|
|
return
|
|
}
|
|
if (
|
|
setting === 'copyPasteDelay' &&
|
|
settingsStore.getState().copyPasteDelay !== value &&
|
|
typeof value === 'number'
|
|
) {
|
|
settingsStore.setState({ copyPasteDelay: value })
|
|
return
|
|
}
|
|
if (
|
|
setting === 'copyPasteSequencePinnedDelay' &&
|
|
settingsStore.getState().copyPasteSequencePinnedDelay !== value &&
|
|
typeof value === 'number'
|
|
) {
|
|
settingsStore.setState({ copyPasteSequencePinnedDelay: value })
|
|
return
|
|
}
|
|
if (
|
|
setting === 'copyPasteSequenceIsReversOrder' &&
|
|
settingsStore.getState().copyPasteSequenceIsReversOrder !== value &&
|
|
typeof value === 'boolean'
|
|
) {
|
|
settingsStore.setState({ copyPasteSequenceIsReversOrder: value })
|
|
return
|
|
}
|
|
if (
|
|
setting === 'pasteSequenceEachSeparator' &&
|
|
settingsStore.getState().pasteSequenceEachSeparator !== value &&
|
|
typeof value === 'string'
|
|
) {
|
|
settingsStore.setState({ pasteSequenceEachSeparator: value })
|
|
return
|
|
}
|
|
if (
|
|
setting === 'isHistoryEnabled' &&
|
|
settingsStore.getState().isHistoryEnabled !== value &&
|
|
typeof value === 'boolean'
|
|
) {
|
|
settingsStore.setState({ isHistoryEnabled: value })
|
|
return
|
|
}
|
|
if (
|
|
setting === 'isHistoryAutoUpdateOnCaputureEnabled' &&
|
|
settingsStore.getState().isHistoryAutoUpdateOnCaputureEnabled !== value &&
|
|
typeof value === 'boolean'
|
|
) {
|
|
settingsStore.setState({ isHistoryAutoUpdateOnCaputureEnabled: value })
|
|
return
|
|
}
|
|
if (
|
|
setting === 'screenLockPassCode' &&
|
|
settingsStore.getState().screenLockPassCode !== value &&
|
|
typeof value === 'string'
|
|
) {
|
|
settingsStore.setState({ screenLockPassCode: value })
|
|
return
|
|
}
|
|
}
|
|
})
|
|
|
|
export const settingsStoreAtom = atomWithStore(settingsStore)
|
|
|
|
export { showUpdateAppIsLatest, showUpdateChecking }
|
|
|
|
if (import.meta.env.TAURI_DEBUG) {
|
|
// @ts-expect-error
|
|
window.settingsStore = settingsStore
|
|
}
|