mirror of
https://github.com/moku-project/Moku.git
synced 2026-06-13 09:19:56 -05:00
Chore: Remove Old Directory (Prepare for Patches)
This commit is contained in:
+90
-86
@@ -5,34 +5,21 @@ import { open } from '@tauri-apps/plu
|
||||
import { readFile, writeFile } from '@tauri-apps/plugin-fs'
|
||||
import { open as openUrl } from '@tauri-apps/plugin-shell'
|
||||
import { getVersion } from '@tauri-apps/api/app'
|
||||
import { LazyStore } from '@tauri-apps/plugin-store'
|
||||
import { connect, disconnect, setActivity, clearActivity } from 'tauri-plugin-discord-rpc-api'
|
||||
import type {
|
||||
PlatformAdapter,
|
||||
PlatformFeature,
|
||||
ServerLaunchConfig,
|
||||
DiscordPresence,
|
||||
AppUpdateInfo,
|
||||
StorageInfo,
|
||||
ReleaseInfo,
|
||||
UpdateProgress,
|
||||
MigrateProgress,
|
||||
PlatformAdapter, PlatformFeature, Platform,
|
||||
ServerLaunchConfig, DiscordPresence,
|
||||
AppUpdateInfo, StorageInfo, ReleaseInfo,
|
||||
UpdateProgress, MigrateProgress,
|
||||
} from '$lib/platform-adapters/types'
|
||||
|
||||
const APP_ID = '1487894643613106298'
|
||||
|
||||
const storeCache = new Map<string, LazyStore>()
|
||||
|
||||
function getStore(key: string): LazyStore {
|
||||
if (!storeCache.has(key)) {
|
||||
storeCache.set(key, new LazyStore(`${key}.json`, { autoSave: false }))
|
||||
}
|
||||
return storeCache.get(key)!
|
||||
}
|
||||
const DISCORD_APP_ID = '1487894643613106298'
|
||||
|
||||
export class TauriAdapter implements PlatformAdapter {
|
||||
readonly platform: Platform = 'tauri'
|
||||
|
||||
async init() {
|
||||
await connect(APP_ID).catch(() => {})
|
||||
await connect(DISCORD_APP_ID).catch(() => {})
|
||||
}
|
||||
|
||||
async destroy() {
|
||||
@@ -41,47 +28,54 @@ export class TauriAdapter implements PlatformAdapter {
|
||||
|
||||
isSupported(feature: PlatformFeature): boolean {
|
||||
const supported: PlatformFeature[] = [
|
||||
'server-management',
|
||||
'biometric-auth',
|
||||
'native-window',
|
||||
'filesystem',
|
||||
'app-updates',
|
||||
'discord-rpc',
|
||||
'server-management', 'biometric-auth',
|
||||
'native-window', 'filesystem', 'app-updates', 'discord-rpc',
|
||||
]
|
||||
return supported.includes(feature)
|
||||
}
|
||||
|
||||
async getAppDir(): Promise<string> {
|
||||
return invoke<string>('get_app_dir')
|
||||
}
|
||||
|
||||
async loadStore(key: string): Promise<unknown> {
|
||||
return getStore(key).get<unknown>(key) ?? null
|
||||
try {
|
||||
return await invoke<unknown>('load_store', { key })
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async saveStore(key: string, value: unknown): Promise<void> {
|
||||
const store = getStore(key)
|
||||
await store.set(key, value)
|
||||
await store.save()
|
||||
await invoke('save_store', { key, value: JSON.stringify(value) })
|
||||
}
|
||||
|
||||
async launchServer(config: ServerLaunchConfig) {
|
||||
await invoke('spawn_server', {
|
||||
binary: config.binary ?? '',
|
||||
binaryArgs: config.binaryArgs ?? null,
|
||||
webUiEnabled: config.webUiEnabled ?? false,
|
||||
})
|
||||
async storeCredential(key: string, value: string): Promise<void> {
|
||||
await invoke('store_credential', { key, value })
|
||||
}
|
||||
|
||||
async stopServer() {
|
||||
await invoke('kill_server')
|
||||
async getCredential(key: string): Promise<string | null> {
|
||||
try {
|
||||
return await invoke<string | null>('get_credential', { key })
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async getServerStatus(): Promise<'running' | 'stopped' | 'error'> {
|
||||
return 'stopped'
|
||||
async authenticateBiometric(): Promise<boolean> {
|
||||
try {
|
||||
await invoke('windows_hello_authenticate', { reason: 'Authenticate to access Moku' })
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async readFile(path: string): Promise<Uint8Array> {
|
||||
return readFile(path)
|
||||
}
|
||||
|
||||
async writeFile(path: string, data: Uint8Array) {
|
||||
async writeFile(path: string, data: Uint8Array): Promise<void> {
|
||||
await writeFile(path, data)
|
||||
}
|
||||
|
||||
@@ -94,11 +88,11 @@ export class TauriAdapter implements PlatformAdapter {
|
||||
return invoke('check_path_exists', { path })
|
||||
}
|
||||
|
||||
async createDirectory(path: string) {
|
||||
async createDirectory(path: string): Promise<void> {
|
||||
await invoke('create_directory', { path })
|
||||
}
|
||||
|
||||
async openPath(path: string) {
|
||||
async openPath(path: string): Promise<void> {
|
||||
await invoke('open_path', { path })
|
||||
}
|
||||
|
||||
@@ -110,46 +104,57 @@ export class TauriAdapter implements PlatformAdapter {
|
||||
return invoke('get_storage_info', { downloadsPath })
|
||||
}
|
||||
|
||||
async migrateDownloads(src: string, dst: string) {
|
||||
async migrateDownloads(src: string, dst: string): Promise<void> {
|
||||
await invoke('migrate_downloads', { src, dst })
|
||||
}
|
||||
|
||||
async authenticateBiometric(): Promise<boolean> {
|
||||
try {
|
||||
await invoke('windows_hello_authenticate', { reason: 'Authenticate to access Moku' })
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
async getAutoBackupDir(): Promise<string> {
|
||||
return invoke('get_auto_backup_dir')
|
||||
}
|
||||
|
||||
async setTitle(title: string) {
|
||||
async launchServer(config: ServerLaunchConfig): Promise<void> {
|
||||
await invoke('spawn_server', {
|
||||
binary: config.binary ?? '',
|
||||
binaryArgs: config.binaryArgs ?? null,
|
||||
webUiEnabled: config.webUiEnabled ?? false,
|
||||
})
|
||||
}
|
||||
|
||||
async stopServer(): Promise<void> {
|
||||
await invoke('kill_server')
|
||||
}
|
||||
|
||||
async getServerStatus(): Promise<'running' | 'stopped' | 'error'> {
|
||||
return 'stopped'
|
||||
}
|
||||
|
||||
async setTitle(title: string): Promise<void> {
|
||||
await getCurrentWindow().setTitle(title)
|
||||
}
|
||||
|
||||
async minimize() {
|
||||
async minimize(): Promise<void> {
|
||||
await getCurrentWindow().minimize()
|
||||
}
|
||||
|
||||
async maximize() {
|
||||
async maximize(): Promise<void> {
|
||||
const win = getCurrentWindow()
|
||||
await (await win.isMaximized() ? win.unmaximize() : win.maximize())
|
||||
}
|
||||
|
||||
async close() {
|
||||
async close(): Promise<void> {
|
||||
await getCurrentWindow().close()
|
||||
}
|
||||
|
||||
async toggleFullscreen() {
|
||||
async toggleFullscreen(): Promise<void> {
|
||||
const win = getCurrentWindow()
|
||||
await win.setFullscreen(!await win.isFullscreen())
|
||||
}
|
||||
|
||||
async setDiscordPresence(presence: DiscordPresence) {
|
||||
async setDiscordPresence(presence: DiscordPresence): Promise<void> {
|
||||
await setActivity(presence).catch(() => {})
|
||||
}
|
||||
|
||||
async clearDiscordPresence() {
|
||||
async clearDiscordPresence(): Promise<void> {
|
||||
await clearActivity().catch(() => {})
|
||||
}
|
||||
|
||||
@@ -157,42 +162,57 @@ export class TauriAdapter implements PlatformAdapter {
|
||||
return getVersion()
|
||||
}
|
||||
|
||||
async openExternal(url: string) {
|
||||
async openExternal(url: string): Promise<void> {
|
||||
await openUrl(url)
|
||||
}
|
||||
|
||||
async restartApp() {
|
||||
await invoke('restart_app')
|
||||
}
|
||||
|
||||
async exitApp() {
|
||||
await invoke('exit_app')
|
||||
}
|
||||
|
||||
async checkForAppUpdate(): Promise<AppUpdateInfo | null> {
|
||||
const releases = await invoke<Array<{ tag_name: string; html_url: string; body: string }>>('list_releases')
|
||||
const current = await getVersion()
|
||||
const valid = releases.filter(r => r.tag_name?.trim())
|
||||
if (!valid.length) return null
|
||||
|
||||
const parse = (v: string) => v.replace(/^v/, '').split('.').map(Number)
|
||||
const latest = valid.map(r => r.tag_name).sort((a, b) => {
|
||||
const pa = parse(a), pb = parse(b)
|
||||
for (let i = 0; i < 3; i++) if ((pb[i] ?? 0) !== (pa[i] ?? 0)) return (pb[i] ?? 0) - (pa[i] ?? 0)
|
||||
return 0
|
||||
})[0]
|
||||
|
||||
const pa = parse(latest), pb = parse(current)
|
||||
if (!pa.some((n, i) => n > (pb[i] ?? 0))) return null
|
||||
|
||||
const rel = valid.find(r => r.tag_name === latest)!
|
||||
return { version: latest.replace(/^v/, ''), url: rel.html_url, notes: rel.body }
|
||||
}
|
||||
|
||||
async installAppUpdate(tag: string): Promise<void> {
|
||||
await invoke('download_and_install_update', { tag })
|
||||
}
|
||||
|
||||
async restartApp(): Promise<void> {
|
||||
await invoke('restart_app')
|
||||
}
|
||||
|
||||
async exitApp(): Promise<void> {
|
||||
await invoke('exit_app')
|
||||
}
|
||||
|
||||
async listReleases(): Promise<ReleaseInfo[]> {
|
||||
const all = await invoke<ReleaseInfo[]>('list_releases')
|
||||
return all.filter(r => typeof r.tag_name === 'string' && r.tag_name.trim())
|
||||
}
|
||||
|
||||
async installAppUpdate(tag: string) {
|
||||
await invoke('download_and_install_update', { tag })
|
||||
async clearMokuCache(): Promise<void> {
|
||||
await invoke('clear_moku_cache')
|
||||
}
|
||||
|
||||
async clearSuwayomiCache(): Promise<void> {
|
||||
await invoke('clear_suwayomi_cache')
|
||||
}
|
||||
|
||||
async resetSuwayomiData(): Promise<void> {
|
||||
await invoke('reset_suwayomi_data')
|
||||
}
|
||||
|
||||
async onUpdateProgress(cb: (p: UpdateProgress) => void): Promise<() => void> {
|
||||
@@ -203,22 +223,6 @@ export class TauriAdapter implements PlatformAdapter {
|
||||
return listen('update-launching', cb)
|
||||
}
|
||||
|
||||
async getAutoBackupDir(): Promise<string> {
|
||||
return invoke('get_auto_backup_dir')
|
||||
}
|
||||
|
||||
async clearMokuCache() {
|
||||
await invoke('clear_moku_cache')
|
||||
}
|
||||
|
||||
async clearSuwayomiCache() {
|
||||
await invoke('clear_suwayomi_cache')
|
||||
}
|
||||
|
||||
async resetSuwayomiData() {
|
||||
await invoke('reset_suwayomi_data')
|
||||
}
|
||||
|
||||
async onMigrateProgress(cb: (p: MigrateProgress) => void): Promise<() => void> {
|
||||
return listen<MigrateProgress>('migrate_progress', e => cb(e.payload))
|
||||
}
|
||||
@@ -6,32 +6,36 @@ function parse(tag: string): number[] {
|
||||
return tag.replace(/^v/, '').split('.').map(Number)
|
||||
}
|
||||
|
||||
function compare(a: number[], b: number[]): number {
|
||||
function isNewer(candidate: number[], current: number[]): boolean {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
if ((a[i] ?? 0) !== (b[i] ?? 0)) return (b[i] ?? 0) - (a[i] ?? 0)
|
||||
if ((candidate[i] ?? 0) > (current[i] ?? 0)) return true
|
||||
if ((candidate[i] ?? 0) < (current[i] ?? 0)) return false
|
||||
}
|
||||
return 0
|
||||
return false
|
||||
}
|
||||
|
||||
export async function checkForUpdateSilently(): Promise<void> {
|
||||
try {
|
||||
const [currentVersion, releases] = await Promise.all([
|
||||
getVersion(),
|
||||
invoke<Array<{ tag_name: string; html_url: string }>>('list_releases'),
|
||||
invoke<Array<{ tag_name: string }>>('list_releases'),
|
||||
])
|
||||
|
||||
const valid = releases.filter(r => typeof r.tag_name === 'string' && r.tag_name.trim())
|
||||
const valid = releases.filter(r => r.tag_name?.trim())
|
||||
if (!valid.length) return
|
||||
|
||||
const latestTag = valid
|
||||
const latest = valid
|
||||
.map(r => r.tag_name)
|
||||
.sort((a, b) => compare(parse(a), parse(b)))[0]
|
||||
.replace(/^v/, '')
|
||||
.sort((a, b) => {
|
||||
const pa = parse(a), pb = parse(b)
|
||||
for (let i = 0; i < 3; i++) if ((pb[i] ?? 0) !== (pa[i] ?? 0)) return (pb[i] ?? 0) - (pa[i] ?? 0)
|
||||
return 0
|
||||
})[0]
|
||||
|
||||
if (compare(parse(latestTag), parse(currentVersion)) < 0) {
|
||||
if (isNewer(parse(latest), parse(currentVersion))) {
|
||||
toast({
|
||||
kind: 'info',
|
||||
message: `Update available — v${latestTag}`,
|
||||
message: `Update available — ${latest}`,
|
||||
detail: 'Open Settings → About to install.',
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user