download & provision
This commit is contained in:
@@ -0,0 +1,121 @@
|
|||||||
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
import { BaseDirectory, appLocalDataDir } from '@tauri-apps/api/path'
|
||||||
|
import { tempDir } from '@tauri-apps/api/path'
|
||||||
|
import { copyFile, mkdir, remove } from '@tauri-apps/plugin-fs'
|
||||||
|
import { writeFile } from '@tauri-apps/plugin-fs'
|
||||||
|
import { fetch } from '@tauri-apps/plugin-http'
|
||||||
|
import { platform } from '@tauri-apps/plugin-os'
|
||||||
|
import { Command } from '@tauri-apps/plugin-shell'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if rclone is installed and accessible from the system PATH
|
||||||
|
* @returns {Promise<boolean>} True if rclone is installed and working
|
||||||
|
*/
|
||||||
|
export async function checkRcloneInstalled() {
|
||||||
|
const output = await Command.create('rclone').execute()
|
||||||
|
// console.log('[checkRcloneInstalled] output', output)
|
||||||
|
return (
|
||||||
|
output.stdout.includes('Available commands') || output.stderr.includes('Available commands')
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if rclone is bundled with the application in the app's local data directory
|
||||||
|
* @returns {Promise<boolean>} True if bundled rclone is present and working
|
||||||
|
*/
|
||||||
|
export async function checkRcloneBundled() {
|
||||||
|
const output = await Command.create('./rclone', [], {
|
||||||
|
cwd: `${await appLocalDataDir()}`,
|
||||||
|
}).execute()
|
||||||
|
// console.log('[checkRcloneBundled] output', output)
|
||||||
|
return (
|
||||||
|
output.stdout.includes('Available commands') || output.stderr.includes('Available commands')
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads and provisions the latest version of rclone for the current platform
|
||||||
|
* @throws {Error} If architecture detection fails or installation is unsuccessful
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
export async function provisionRclone() {
|
||||||
|
const currentVersionString = await fetch('https://downloads.rclone.org/version.txt').then(
|
||||||
|
(res) => res.text()
|
||||||
|
)
|
||||||
|
console.log('currentVersionString', currentVersionString)
|
||||||
|
|
||||||
|
const currentVersion = currentVersionString.split('v')?.[1]?.trim()
|
||||||
|
|
||||||
|
if (!currentVersion) {
|
||||||
|
console.error('Failed to get latest version')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.log('currentVersion', currentVersion)
|
||||||
|
|
||||||
|
const currentPlatform = platform()
|
||||||
|
console.log('currentPlatform', currentPlatform)
|
||||||
|
|
||||||
|
const currentOs =
|
||||||
|
currentPlatform === 'macos' ? 'osx' : currentPlatform === 'windows' ? 'win' : 'linux'
|
||||||
|
console.log('currentOs', currentOs)
|
||||||
|
|
||||||
|
let tempDirPath = await tempDir()
|
||||||
|
if (tempDirPath.endsWith('/')) {
|
||||||
|
tempDirPath = tempDirPath.slice(0, -1)
|
||||||
|
}
|
||||||
|
console.log('tempDirPath', tempDirPath)
|
||||||
|
|
||||||
|
const arch = (await invoke('get_arch')) as 'arm64' | 'amd64' | '386' | 'unknown'
|
||||||
|
console.log('arch', arch)
|
||||||
|
|
||||||
|
if (arch === 'unknown') {
|
||||||
|
throw new Error('Failed to get architecture, please try again later.')
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadUrl = `https://downloads.rclone.org/v${currentVersion}/rclone-v${currentVersion}-${currentOs}-${arch}.zip`
|
||||||
|
console.log('downloadUrl', downloadUrl)
|
||||||
|
|
||||||
|
const downloadedFile = await fetch(downloadUrl).then((res) => res.arrayBuffer())
|
||||||
|
|
||||||
|
await remove('rclone', {
|
||||||
|
recursive: true,
|
||||||
|
baseDir: BaseDirectory.Temp,
|
||||||
|
})
|
||||||
|
|
||||||
|
await mkdir('rclone', {
|
||||||
|
baseDir: BaseDirectory.Temp,
|
||||||
|
})
|
||||||
|
|
||||||
|
const zipPath = `${tempDirPath}/rclone/rclone-v${currentVersion}-${currentOs}-${arch}.zip`
|
||||||
|
console.log('zipPath', zipPath)
|
||||||
|
|
||||||
|
await writeFile(zipPath, new Uint8Array(downloadedFile))
|
||||||
|
|
||||||
|
await invoke('unzip_file', {
|
||||||
|
zipPath,
|
||||||
|
outputFolder: `${tempDirPath}/rclone/rclone-ui`,
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('Successfully unzipped file')
|
||||||
|
|
||||||
|
const unarchivedPath = `${tempDirPath}/rclone/rclone-ui/rclone-v${currentVersion}-${currentOs}-${arch}`
|
||||||
|
console.log('unarchivedPath', unarchivedPath)
|
||||||
|
|
||||||
|
// const unarchivedFolder = await readDir(unarchivedPath)
|
||||||
|
// console.log('unarchivedFolder', unarchivedFolder)
|
||||||
|
|
||||||
|
const rcloneBinaryPath = unarchivedPath + '/' + 'rclone'
|
||||||
|
console.log('rcloneBinaryPath', rcloneBinaryPath)
|
||||||
|
|
||||||
|
if (!rcloneBinaryPath) {
|
||||||
|
throw new Error('Could not find rclone binary in zip')
|
||||||
|
}
|
||||||
|
|
||||||
|
await copyFile(rcloneBinaryPath, `${await appLocalDataDir()}/rclone`)
|
||||||
|
|
||||||
|
const hasInstalled = await checkRcloneInstalled()
|
||||||
|
|
||||||
|
if (!hasInstalled) {
|
||||||
|
throw new Error('Failed to install rclone')
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
|
import { appLocalDataDir } from '@tauri-apps/api/path'
|
||||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||||
import { message } from '@tauri-apps/plugin-dialog'
|
import { confirm, message } from '@tauri-apps/plugin-dialog'
|
||||||
|
import {} from '@tauri-apps/plugin-fs'
|
||||||
import { debug, error, info, trace, warn } from '@tauri-apps/plugin-log'
|
import { debug, error, info, trace, warn } from '@tauri-apps/plugin-log'
|
||||||
import { exit } from '@tauri-apps/plugin-process'
|
import { exit } from '@tauri-apps/plugin-process'
|
||||||
import { Command } from '@tauri-apps/plugin-shell'
|
import { Command } from '@tauri-apps/plugin-shell'
|
||||||
import { listRemotes } from './lib/rclone'
|
import { listRemotes } from './lib/rclone/api'
|
||||||
|
import { checkRcloneBundled, checkRcloneInstalled, provisionRclone } from './lib/rclone/init'
|
||||||
import { useStore } from './lib/store'
|
import { useStore } from './lib/store'
|
||||||
import { initLoadingTray, initTray, rebuildTrayMenu } from './lib/tray'
|
import { initLoadingTray, initTray, rebuildTrayMenu } from './lib/tray'
|
||||||
|
|
||||||
@@ -31,23 +34,69 @@ console.log('main')
|
|||||||
console.error('main')
|
console.error('main')
|
||||||
|
|
||||||
async function startRclone() {
|
async function startRclone() {
|
||||||
|
let hasLocalRclone = false
|
||||||
|
try {
|
||||||
|
hasLocalRclone = await checkRcloneInstalled()
|
||||||
|
console.log('hasLocalRclone', hasLocalRclone)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to check if rclone is installed', error)
|
||||||
|
}
|
||||||
|
console.log('hasLocalRclone', hasLocalRclone)
|
||||||
|
|
||||||
|
let hasBundledRclone = false
|
||||||
|
try {
|
||||||
|
hasBundledRclone = await checkRcloneBundled()
|
||||||
|
console.log('hasBundledRclone', hasBundledRclone)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to check if rclone is bundled', error)
|
||||||
|
}
|
||||||
|
console.log('hasBundledRclone', hasBundledRclone)
|
||||||
|
|
||||||
|
if (!hasLocalRclone && !hasBundledRclone) {
|
||||||
|
try {
|
||||||
|
await provisionRclone()
|
||||||
|
} catch (error) {
|
||||||
|
await confirm(error?.message || 'Failed to provision rclone, please try again later.', {
|
||||||
|
title: 'Error',
|
||||||
|
kind: 'error',
|
||||||
|
})
|
||||||
|
return await exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const remotes = await listRemotes()
|
const remotes = await listRemotes()
|
||||||
console.log('rclone already running', remotes)
|
console.log('rclone rcd already running')
|
||||||
useStore.setState({ rcloneLoaded: true })
|
useStore.setState({ rcloneLoaded: true })
|
||||||
useStore.setState({ remotes: remotes })
|
useStore.setState({ remotes: remotes })
|
||||||
return
|
return
|
||||||
} catch (e) {
|
} catch {}
|
||||||
console.error('Failed to start rclone', e)
|
|
||||||
}
|
|
||||||
|
|
||||||
const command = Command.sidecar('binaries/rclone', [
|
//! this works
|
||||||
'rcd',
|
// const command = Command.sidecar('binaries/rclone', [
|
||||||
'--rc-no-auth',
|
// 'rcd',
|
||||||
'--rc-serve',
|
// '--rc-no-auth',
|
||||||
// '-rc-addr',
|
// '--rc-serve',
|
||||||
// ':5572',
|
// // '-rc-addr',
|
||||||
])
|
// // ':5572',
|
||||||
|
// ])
|
||||||
|
|
||||||
|
//! sidecar does not work with global or appdata binaries
|
||||||
|
const command = Command.create(
|
||||||
|
hasLocalRclone ? 'rclone' : './rclone',
|
||||||
|
[
|
||||||
|
'rcd',
|
||||||
|
'--rc-no-auth',
|
||||||
|
'--rc-serve',
|
||||||
|
// '-rc-addr',
|
||||||
|
// ':5572',
|
||||||
|
],
|
||||||
|
hasLocalRclone
|
||||||
|
? undefined
|
||||||
|
: {
|
||||||
|
cwd: `${await appLocalDataDir()}`,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
command.addListener('close', async (event) => {
|
command.addListener('close', async (event) => {
|
||||||
console.log('close', event)
|
console.log('close', event)
|
||||||
@@ -65,11 +114,11 @@ async function startRclone() {
|
|||||||
console.log('error', event)
|
console.log('error', event)
|
||||||
})
|
})
|
||||||
|
|
||||||
// console.log('command', command)
|
//! so we have to do this:
|
||||||
|
//! not await the call
|
||||||
|
const childProcess = command.execute()
|
||||||
|
|
||||||
const childProcess = await command.spawn()
|
await new Promise((resolve) => setTimeout(resolve, 200))
|
||||||
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
||||||
|
|
||||||
useStore.setState({ rcloneLoaded: true })
|
useStore.setState({ rcloneLoaded: true })
|
||||||
|
|
||||||
@@ -94,7 +143,3 @@ getCurrentWindow().listen('rebuild-tray', async (e) => {
|
|||||||
initLoadingTray()
|
initLoadingTray()
|
||||||
.then(() => startRclone())
|
.then(() => startRclone())
|
||||||
.then(() => initTray())
|
.then(() => initTray())
|
||||||
|
|
||||||
// await initLoadingTray()
|
|
||||||
// await startRclone()
|
|
||||||
// await initTray()
|
|
||||||
|
|||||||
Generated
+157
@@ -17,6 +17,17 @@ version = "2.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cipher",
|
||||||
|
"cpufeatures",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.7.8"
|
version = "0.7.8"
|
||||||
@@ -113,6 +124,7 @@ dependencies = [
|
|||||||
"tauri-plugin-shell",
|
"tauri-plugin-shell",
|
||||||
"tauri-plugin-single-instance",
|
"tauri-plugin-single-instance",
|
||||||
"tauri-plugin-store",
|
"tauri-plugin-store",
|
||||||
|
"zip",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -347,6 +359,12 @@ version = "0.22.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64ct"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@@ -522,6 +540,27 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bzip2"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8"
|
||||||
|
dependencies = [
|
||||||
|
"bzip2-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bzip2-sys"
|
||||||
|
version = "0.1.11+1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cairo-rs"
|
name = "cairo-rs"
|
||||||
version = "0.18.5"
|
version = "0.18.5"
|
||||||
@@ -595,6 +634,8 @@ version = "1.2.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7"
|
checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"jobserver",
|
||||||
|
"libc",
|
||||||
"shlex",
|
"shlex",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -656,6 +697,16 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cipher"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"inout",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cocoa"
|
name = "cocoa"
|
||||||
version = "0.26.0"
|
version = "0.26.0"
|
||||||
@@ -705,6 +756,12 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "constant_time_eq"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "convert_case"
|
name = "convert_case"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@@ -953,6 +1010,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer",
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1771,6 +1829,15 @@ version = "0.4.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hmac"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "home"
|
name = "home"
|
||||||
version = "0.5.11"
|
version = "0.5.11"
|
||||||
@@ -2112,6 +2179,15 @@ dependencies = [
|
|||||||
"cfb",
|
"cfb",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inout"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.10.1"
|
version = "2.10.1"
|
||||||
@@ -2194,6 +2270,15 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jobserver"
|
||||||
|
version = "0.1.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.76"
|
version = "0.3.76"
|
||||||
@@ -2942,12 +3027,35 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "password-hash"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pathdiff"
|
name = "pathdiff"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
|
checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pbkdf2"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
"hmac",
|
||||||
|
"password-hash",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.1"
|
version = "2.3.1"
|
||||||
@@ -6391,6 +6499,55 @@ dependencies = [
|
|||||||
"syn 2.0.95",
|
"syn 2.0.95",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zip"
|
||||||
|
version = "0.6.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
|
||||||
|
dependencies = [
|
||||||
|
"aes",
|
||||||
|
"byteorder",
|
||||||
|
"bzip2",
|
||||||
|
"constant_time_eq",
|
||||||
|
"crc32fast",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"flate2",
|
||||||
|
"hmac",
|
||||||
|
"pbkdf2",
|
||||||
|
"sha1",
|
||||||
|
"time",
|
||||||
|
"zstd",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd"
|
||||||
|
version = "0.11.2+zstd.1.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4"
|
||||||
|
dependencies = [
|
||||||
|
"zstd-safe",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-safe"
|
||||||
|
version = "5.0.2+zstd.1.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"zstd-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-sys"
|
||||||
|
version = "2.0.13+zstd.1.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant"
|
name = "zvariant"
|
||||||
version = "4.0.0"
|
version = "4.0.0"
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ tauri-plugin-process = "2"
|
|||||||
tauri-plugin-notification = { version = "2.0.0", features = [ "windows7-compat" ] }
|
tauri-plugin-notification = { version = "2.0.0", features = [ "windows7-compat" ] }
|
||||||
tauri-plugin-os = "2"
|
tauri-plugin-os = "2"
|
||||||
fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" }
|
fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" }
|
||||||
|
zip = "0.6.6"
|
||||||
|
|
||||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||||
tauri-plugin-single-instance = "2.2.0"
|
tauri-plugin-single-instance = "2.2.0"
|
||||||
|
|||||||
@@ -167,6 +167,11 @@
|
|||||||
{
|
{
|
||||||
"identifier": "shell:allow-execute",
|
"identifier": "shell:allow-execute",
|
||||||
"allow": [
|
"allow": [
|
||||||
|
{
|
||||||
|
"name": "./rclone",
|
||||||
|
"cmd": "./rclone",
|
||||||
|
"args": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "rclone",
|
"name": "rclone",
|
||||||
"cmd": "rclone",
|
"cmd": "rclone",
|
||||||
@@ -181,21 +186,6 @@
|
|||||||
"name": "mount",
|
"name": "mount",
|
||||||
"cmd": "mount",
|
"cmd": "mount",
|
||||||
"args": true
|
"args": true
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "qjs",
|
|
||||||
"cmd": "qjs",
|
|
||||||
"args": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "fuse",
|
|
||||||
"cmd": "go-nfsv4",
|
|
||||||
"args": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "mount_nfs",
|
|
||||||
"cmd": "mount_nfs",
|
|
||||||
"args": true
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -206,6 +196,16 @@
|
|||||||
"name": "binaries/rclone",
|
"name": "binaries/rclone",
|
||||||
"args": true,
|
"args": true,
|
||||||
"sidecar": true
|
"sidecar": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "./rclone",
|
||||||
|
"args": true,
|
||||||
|
"sidecar": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "rclone",
|
||||||
|
"args": true,
|
||||||
|
"sidecar": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -235,6 +235,22 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"identifier": "fs:allow-mkdir",
|
||||||
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "/**"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "fs:allow-remove",
|
||||||
|
"allow": [
|
||||||
|
{
|
||||||
|
"path": "/**"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"opener:default",
|
"opener:default",
|
||||||
"positioner:default",
|
"positioner:default",
|
||||||
{
|
{
|
||||||
@@ -245,6 +261,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://www.google.com"
|
"url": "https://www.google.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://downloads.rclone.org/**"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/**"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,6 +6,65 @@
|
|||||||
// cwd: String,
|
// cwd: String,
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
use std::fs::{self, File};
|
||||||
|
use std::path::Path;
|
||||||
|
use zip::ZipArchive;
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
fn unzip_file(zip_path: &str, output_folder: &str) -> Result<(), String> {
|
||||||
|
// Open the zip file
|
||||||
|
let file = File::open(zip_path).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
// Create output directory if it doesn't exist
|
||||||
|
fs::create_dir_all(output_folder).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
// Create ZIP archive reader
|
||||||
|
let mut archive = ZipArchive::new(file).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
// Extract everything
|
||||||
|
for i in 0..archive.len() {
|
||||||
|
let mut file = archive.by_index(i).map_err(|e| e.to_string())?;
|
||||||
|
let outpath = Path::new(output_folder).join(file.name());
|
||||||
|
|
||||||
|
if file.name().ends_with('/') {
|
||||||
|
fs::create_dir_all(&outpath).map_err(|e| e.to_string())?;
|
||||||
|
} else {
|
||||||
|
if let Some(p) = outpath.parent() {
|
||||||
|
fs::create_dir_all(p).map_err(|e| e.to_string())?;
|
||||||
|
}
|
||||||
|
let mut outfile = File::create(&outpath).map_err(|e| e.to_string())?;
|
||||||
|
std::io::copy(&mut file, &mut outfile).map_err(|e| e.to_string())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get and set permissions (Unix only)
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
if let Some(mode) = file.unix_mode() {
|
||||||
|
fs::set_permissions(&outpath, fs::Permissions::from_mode(mode))
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
fn get_arch() -> String {
|
||||||
|
let arch = std::env::consts::ARCH;
|
||||||
|
|
||||||
|
match arch {
|
||||||
|
"aarch64" => "arm64".to_string(),
|
||||||
|
"x86_64" => "amd64".to_string(),
|
||||||
|
"i386" => "386".to_string(),
|
||||||
|
_ => "unknown".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
let mut app = tauri::Builder::default()
|
let mut app = tauri::Builder::default()
|
||||||
@@ -30,6 +89,7 @@ pub fn run() {
|
|||||||
.plugin(tauri_plugin_log::Builder::new().build())
|
.plugin(tauri_plugin_log::Builder::new().build())
|
||||||
.plugin(tauri_plugin_shell::init())
|
.plugin(tauri_plugin_shell::init())
|
||||||
.plugin(tauri_plugin_opener::init())
|
.plugin(tauri_plugin_opener::init())
|
||||||
|
.invoke_handler(tauri::generate_handler![unzip_file, get_arch])
|
||||||
.setup(|_app| Ok(()))
|
.setup(|_app| Ok(()))
|
||||||
// .setup(|app| {
|
// .setup(|app| {
|
||||||
// if cfg!(debug_assertions) {
|
// if cfg!(debug_assertions) {
|
||||||
|
|||||||
Reference in New Issue
Block a user