update nextui > heroui, tailwind, vite, onboard, comments, fixes
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
export function formatBytes(bytes: number) {
|
export function formatBytes(bytes: number) {
|
||||||
// format bytes in to a readable format like (MB, GB, etc), depending on how big the number is
|
|
||||||
if (bytes < 1024) {
|
if (bytes < 1024) {
|
||||||
return `${bytes} B`
|
return `${bytes} B`
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-4
@@ -3,16 +3,20 @@ import { fetch } from '@tauri-apps/plugin-http'
|
|||||||
import { usePersistedStore } from './store'
|
import { usePersistedStore } from './store'
|
||||||
|
|
||||||
export async function validateLicense(licenseKey: string) {
|
export async function validateLicense(licenseKey: string) {
|
||||||
|
console.log('[validateLicense]')
|
||||||
|
|
||||||
let id
|
let id
|
||||||
|
|
||||||
try {
|
try {
|
||||||
id = await invoke('get_uid')
|
id = await invoke('get_uid')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.error('[validateLicense] failed to build unique identifier')
|
||||||
console.error(JSON.stringify(e))
|
console.error(JSON.stringify(e))
|
||||||
throw new Error('Failed to build unique identifier. Please try again later.')
|
throw new Error('Failed to build unique identifier. Please try again later.')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
|
console.error('[validateLicense] missing unique identifier')
|
||||||
throw new Error('Failed to build unique identifier. Please try again later.')
|
throw new Error('Failed to build unique identifier. Please try again later.')
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,34 +29,41 @@ export async function validateLicense(licenseKey: string) {
|
|||||||
})
|
})
|
||||||
.then((r) => r.json())
|
.then((r) => r.json())
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
|
console.error('[validateLicense] failed to validate license')
|
||||||
console.error(JSON.stringify(e))
|
console.error(JSON.stringify(e))
|
||||||
throw new Error('Failed to validate license. Are you connected to the internet?')
|
throw new Error('Failed to validate license. Are you connected to the internet?')
|
||||||
})
|
})
|
||||||
|
|
||||||
// console.log(JSON.stringify(validationResponse))
|
|
||||||
|
|
||||||
if (validationResponse.error) {
|
if (validationResponse.error) {
|
||||||
|
console.error('[validateLicense] failed to validate license')
|
||||||
throw new Error(validationResponse.error)
|
throw new Error(validationResponse.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validationResponse.valid) {
|
if (!validationResponse.valid) {
|
||||||
|
console.error('[validateLicense] invalid license key')
|
||||||
throw new Error('Invalid license key. Please check your license key and try again.')
|
throw new Error('Invalid license key. Please check your license key and try again.')
|
||||||
}
|
}
|
||||||
|
|
||||||
usePersistedStore.setState({ licenseKey, licenseValid: true })
|
usePersistedStore.setState({ licenseKey, licenseValid: true })
|
||||||
|
|
||||||
|
console.log('[validateLicense] license validated')
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function revokeLicense(licenseKey: string) {
|
export async function revokeLicense(licenseKey: string) {
|
||||||
|
console.log('[revokeLicense]')
|
||||||
|
|
||||||
let id
|
let id
|
||||||
|
|
||||||
try {
|
try {
|
||||||
id = await invoke('get_uid')
|
id = await invoke('get_uid')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.error('[revokeLicense] failed to build unique identifier')
|
||||||
console.error(JSON.stringify(e))
|
console.error(JSON.stringify(e))
|
||||||
throw new Error('Failed to build unique identifier. Please try again later.')
|
throw new Error('Failed to build unique identifier. Please try again later.')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
|
console.error('[revokeLicense] missing unique identifier')
|
||||||
throw new Error('Failed to build unique identifier. Please try again later.')
|
throw new Error('Failed to build unique identifier. Please try again later.')
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,19 +76,22 @@ export async function revokeLicense(licenseKey: string) {
|
|||||||
})
|
})
|
||||||
.then((r) => r.json())
|
.then((r) => r.json())
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
|
console.error('[revokeLicense] failed to revoke license, fetch failed')
|
||||||
console.error(JSON.stringify(e))
|
console.error(JSON.stringify(e))
|
||||||
throw new Error('Failed to revoke license. Are you connected to the internet?')
|
throw new Error('Failed to revoke license. Are you connected to the internet?')
|
||||||
})
|
})
|
||||||
|
|
||||||
// console.log(JSON.stringify(revocationResponse))
|
|
||||||
|
|
||||||
if (revocationResponse.error) {
|
if (revocationResponse.error) {
|
||||||
|
console.error('[revokeLicense] failed to revoke license, has error response')
|
||||||
throw new Error(revocationResponse.error)
|
throw new Error(revocationResponse.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!revocationResponse.revoked) {
|
if (!revocationResponse.revoked) {
|
||||||
|
console.error('[revokeLicense] failed to revoke license, missing revoked response')
|
||||||
throw new Error('Failed to revoke license. Please check your license key and try again.')
|
throw new Error('Failed to revoke license. Please check your license key and try again.')
|
||||||
}
|
}
|
||||||
|
|
||||||
usePersistedStore.setState({ licenseKey: undefined, licenseValid: false })
|
usePersistedStore.setState({ licenseKey: undefined, licenseValid: false })
|
||||||
|
|
||||||
|
console.log('[revokeLicense] license revoked')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import { usePersistedStore, useStore } from './store'
|
|||||||
import { getLoadingTray, getMainTray, rebuildTrayMenu } from './tray'
|
import { getLoadingTray, getMainTray, rebuildTrayMenu } from './tray'
|
||||||
import { lockWindows, openFullWindow, openWindow, unlockWindows } from './window'
|
import { lockWindows, openFullWindow, openWindow, unlockWindows } from './window'
|
||||||
|
|
||||||
// Function to rebuild and update the menu
|
|
||||||
export async function buildMenu() {
|
export async function buildMenu() {
|
||||||
const storeState = useStore.getState()
|
const storeState = useStore.getState()
|
||||||
|
|
||||||
|
|||||||
+43
-18
@@ -24,14 +24,17 @@ function getAuthHeader() {
|
|||||||
|
|
||||||
/* DATA */
|
/* DATA */
|
||||||
export async function listRemotes() {
|
export async function listRemotes() {
|
||||||
|
console.log('[listRemotes] CALLED')
|
||||||
|
|
||||||
const r = await fetch('http://localhost:5572/config/listremotes', {
|
const r = await fetch('http://localhost:5572/config/listremotes', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getAuthHeader(),
|
headers: getAuthHeader(),
|
||||||
}).then((res) => res.json() as Promise<{ remotes: string[] }>)
|
})
|
||||||
// .catch((e) => {
|
.catch((e) => {
|
||||||
// console.log("error", e);
|
console.log('error', e)
|
||||||
// throw e;
|
throw e
|
||||||
// });
|
})
|
||||||
|
.then((res) => res.json() as Promise<{ remotes: string[] }>)
|
||||||
|
|
||||||
if (typeof r?.remotes === 'undefined') {
|
if (typeof r?.remotes === 'undefined') {
|
||||||
throw new Error('Failed to fetch remotes')
|
throw new Error('Failed to fetch remotes')
|
||||||
@@ -41,16 +44,14 @@ export async function listRemotes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getRemote(remote: string) {
|
export async function getRemote(remote: string) {
|
||||||
|
console.log('[getRemote]', remote)
|
||||||
|
|
||||||
const r = await fetch(`http://localhost:5572/config/get?name=${remote}`, {
|
const r = await fetch(`http://localhost:5572/config/get?name=${remote}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getAuthHeader(),
|
headers: getAuthHeader(),
|
||||||
}).then(
|
}).then(
|
||||||
(res) => res.json() as Promise<{ type: string } & Record<string, string | number | boolean>>
|
(res) => res.json() as Promise<{ type: string } & Record<string, string | number | boolean>>
|
||||||
)
|
)
|
||||||
// .catch((e) => {
|
|
||||||
// console.log("error", e);
|
|
||||||
// throw e;
|
|
||||||
// });
|
|
||||||
|
|
||||||
// console.log(JSON.stringify(r, null, 2))
|
// console.log(JSON.stringify(r, null, 2))
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ export async function updateRemote(
|
|||||||
remote: string,
|
remote: string,
|
||||||
parameters: Record<string, string | number | boolean>
|
parameters: Record<string, string | number | boolean>
|
||||||
) {
|
) {
|
||||||
console.log('updateRemote', remote, parameters)
|
console.log('[updateRemote]', remote, parameters)
|
||||||
|
|
||||||
const options = new URLSearchParams()
|
const options = new URLSearchParams()
|
||||||
options.set('name', remote)
|
options.set('name', remote)
|
||||||
@@ -80,7 +81,7 @@ export async function createRemote(
|
|||||||
type: string,
|
type: string,
|
||||||
parameters: Record<string, string | number | boolean>
|
parameters: Record<string, string | number | boolean>
|
||||||
) {
|
) {
|
||||||
console.log('createRemote', name, type, parameters)
|
console.log('[createRemote]', name, type, parameters)
|
||||||
|
|
||||||
const options = new URLSearchParams()
|
const options = new URLSearchParams()
|
||||||
options.set('name', name)
|
options.set('name', name)
|
||||||
@@ -96,6 +97,8 @@ export async function createRemote(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteRemote(remote: string) {
|
export async function deleteRemote(remote: string) {
|
||||||
|
console.log('[deleteRemote]', remote)
|
||||||
|
|
||||||
await fetch(`http://localhost:5572/config/delete?name=${remote}`, {
|
await fetch(`http://localhost:5572/config/delete?name=${remote}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getAuthHeader(),
|
headers: getAuthHeader(),
|
||||||
@@ -105,6 +108,8 @@ export async function deleteRemote(remote: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getMountPoints() {
|
export async function getMountPoints() {
|
||||||
|
console.log('[getMountPoints]')
|
||||||
|
|
||||||
const r = await fetch('http://localhost:5572/mount/listmounts', {
|
const r = await fetch('http://localhost:5572/mount/listmounts', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getAuthHeader(),
|
headers: getAuthHeader(),
|
||||||
@@ -115,8 +120,6 @@ export async function getMountPoints() {
|
|||||||
}>
|
}>
|
||||||
)
|
)
|
||||||
|
|
||||||
// console.log('Mount points:', r)
|
|
||||||
|
|
||||||
if (!Array.isArray(r?.mountPoints)) {
|
if (!Array.isArray(r?.mountPoints)) {
|
||||||
throw new Error('Failed to get mount points')
|
throw new Error('Failed to get mount points')
|
||||||
}
|
}
|
||||||
@@ -125,6 +128,8 @@ export async function getMountPoints() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getBackends() {
|
export async function getBackends() {
|
||||||
|
console.log('[getBackends]')
|
||||||
|
|
||||||
const providers = await fetch('http://localhost:5572/config/providers', {
|
const providers = await fetch('http://localhost:5572/config/providers', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getAuthHeader(),
|
headers: getAuthHeader(),
|
||||||
@@ -149,6 +154,8 @@ export interface ListOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function listPath(remote: string, path: string = '', options: ListOptions = {}) {
|
export async function listPath(remote: string, path: string = '', options: ListOptions = {}) {
|
||||||
|
console.log('[listPath]', remote, path, options)
|
||||||
|
|
||||||
const params = new URLSearchParams()
|
const params = new URLSearchParams()
|
||||||
params.set('fs', `${remote}:`)
|
params.set('fs', `${remote}:`)
|
||||||
params.set('remote', path)
|
params.set('remote', path)
|
||||||
@@ -190,9 +197,11 @@ export async function listPath(remote: string, path: string = '', options: ListO
|
|||||||
|
|
||||||
return response?.list || []
|
return response?.list || []
|
||||||
}
|
}
|
||||||
/* JOBS */
|
|
||||||
|
|
||||||
|
/* JOBS */
|
||||||
export async function listJobs() {
|
export async function listJobs() {
|
||||||
|
console.log('[listJobs]')
|
||||||
|
|
||||||
const allStats = await fetch('http://localhost:5572/core/stats', {
|
const allStats = await fetch('http://localhost:5572/core/stats', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getAuthHeader(),
|
headers: getAuthHeader(),
|
||||||
@@ -273,6 +282,8 @@ export async function listJobs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function stopJob(jobId: number) {
|
export async function stopJob(jobId: number) {
|
||||||
|
console.log('[stopJob]', jobId)
|
||||||
|
|
||||||
await fetch(`http://localhost:5572/job/stopgroup?group=job/${jobId}`, {
|
await fetch(`http://localhost:5572/job/stopgroup?group=job/${jobId}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getAuthHeader(),
|
headers: getAuthHeader(),
|
||||||
@@ -291,6 +302,8 @@ export async function mountRemote({
|
|||||||
mountOptions?: Record<string, string | number | boolean>
|
mountOptions?: Record<string, string | number | boolean>
|
||||||
vfsOptions?: Record<string, string | number | boolean>
|
vfsOptions?: Record<string, string | number | boolean>
|
||||||
}) {
|
}) {
|
||||||
|
console.log('[mountRemote]', remotePath, mountPoint)
|
||||||
|
|
||||||
const options = new URLSearchParams()
|
const options = new URLSearchParams()
|
||||||
options.set('fs', remotePath)
|
options.set('fs', remotePath)
|
||||||
options.set('mountPoint', mountPoint)
|
options.set('mountPoint', mountPoint)
|
||||||
@@ -325,6 +338,8 @@ export async function unmountRemote({
|
|||||||
}: {
|
}: {
|
||||||
mountPoint: string
|
mountPoint: string
|
||||||
}) {
|
}) {
|
||||||
|
console.log('[unmountRemote]', mountPoint)
|
||||||
|
|
||||||
const options = new URLSearchParams()
|
const options = new URLSearchParams()
|
||||||
options.set('mountPoint', mountPoint)
|
options.set('mountPoint', mountPoint)
|
||||||
|
|
||||||
@@ -338,8 +353,6 @@ export async function unmountRemote({
|
|||||||
throw e
|
throw e
|
||||||
})
|
})
|
||||||
|
|
||||||
// console.log('unmountRemote', JSON.stringify(r, null, 2))
|
|
||||||
|
|
||||||
if ('error' in r) {
|
if ('error' in r) {
|
||||||
throw new Error(r.error)
|
throw new Error(r.error)
|
||||||
}
|
}
|
||||||
@@ -348,6 +361,8 @@ export async function unmountRemote({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function unmountAllRemotes() {
|
export async function unmountAllRemotes() {
|
||||||
|
console.log('[unmountAllRemotes]')
|
||||||
|
|
||||||
const r = await fetch('http://localhost:5572/mount/unmountall', {
|
const r = await fetch('http://localhost:5572/mount/unmountall', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getAuthHeader(),
|
headers: getAuthHeader(),
|
||||||
@@ -358,8 +373,6 @@ export async function unmountAllRemotes() {
|
|||||||
throw e
|
throw e
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log('unmountAllRemotes', r)
|
|
||||||
|
|
||||||
if ('error' in r) {
|
if ('error' in r) {
|
||||||
throw new Error(r.error)
|
throw new Error(r.error)
|
||||||
}
|
}
|
||||||
@@ -452,6 +465,8 @@ export async function startSync({
|
|||||||
/* FLAGS */
|
/* FLAGS */
|
||||||
|
|
||||||
export async function getGlobalFlags() {
|
export async function getGlobalFlags() {
|
||||||
|
console.log('[getGlobalFlags]')
|
||||||
|
|
||||||
const r = await fetch('http://localhost:5572/options/get', {
|
const r = await fetch('http://localhost:5572/options/get', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getAuthHeader(),
|
headers: getAuthHeader(),
|
||||||
@@ -461,6 +476,8 @@ export async function getGlobalFlags() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getCopyFlags() {
|
export async function getCopyFlags() {
|
||||||
|
console.log('[getCopyFlags]')
|
||||||
|
|
||||||
const r = await fetch('http://localhost:5572/options/info', {
|
const r = await fetch('http://localhost:5572/options/info', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getAuthHeader(),
|
headers: getAuthHeader(),
|
||||||
@@ -476,6 +493,8 @@ export async function getCopyFlags() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getSyncFlags() {
|
export async function getSyncFlags() {
|
||||||
|
console.log('[getSyncFlags]')
|
||||||
|
|
||||||
const r = await fetch('http://localhost:5572/options/info', {
|
const r = await fetch('http://localhost:5572/options/info', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getAuthHeader(),
|
headers: getAuthHeader(),
|
||||||
@@ -494,6 +513,8 @@ export async function getSyncFlags() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getFilterFlags() {
|
export async function getFilterFlags() {
|
||||||
|
console.log('[getFilterFlags]')
|
||||||
|
|
||||||
const r = await fetch('http://localhost:5572/options/info', {
|
const r = await fetch('http://localhost:5572/options/info', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getAuthHeader(),
|
headers: getAuthHeader(),
|
||||||
@@ -508,6 +529,8 @@ export async function getFilterFlags() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getVfsFlags() {
|
export async function getVfsFlags() {
|
||||||
|
console.log('[getVfsFlags]')
|
||||||
|
|
||||||
const r = await fetch('http://localhost:5572/options/info', {
|
const r = await fetch('http://localhost:5572/options/info', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getAuthHeader(),
|
headers: getAuthHeader(),
|
||||||
@@ -523,6 +546,8 @@ export async function getVfsFlags() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getMountFlags() {
|
export async function getMountFlags() {
|
||||||
|
console.log('[getMountFlags]')
|
||||||
|
|
||||||
const r = await fetch('http://localhost:5572/options/info', {
|
const r = await fetch('http://localhost:5572/options/info', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getAuthHeader(),
|
headers: getAuthHeader(),
|
||||||
|
|||||||
+39
-30
@@ -39,9 +39,10 @@ export async function initRclone() {
|
|||||||
* @returns {Promise<boolean>} True if rclone is installed and working
|
* @returns {Promise<boolean>} True if rclone is installed and working
|
||||||
*/
|
*/
|
||||||
export async function isSystemRcloneInstalled() {
|
export async function isSystemRcloneInstalled() {
|
||||||
|
console.log('[isSystemRcloneInstalled]')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const output = await Command.create('rclone-system').execute()
|
const output = await Command.create('rclone-system').execute()
|
||||||
// console.log('[isSystemRcloneInstalled] output', output)
|
|
||||||
return (
|
return (
|
||||||
output.stdout.includes('Available commands') ||
|
output.stdout.includes('Available commands') ||
|
||||||
output.stderr.includes('Available commands')
|
output.stderr.includes('Available commands')
|
||||||
@@ -56,6 +57,8 @@ export async function isSystemRcloneInstalled() {
|
|||||||
* @returns {Promise<boolean>} True if downloaded rclone is present and working
|
* @returns {Promise<boolean>} True if downloaded rclone is present and working
|
||||||
*/
|
*/
|
||||||
export async function isInternalRcloneInstalled() {
|
export async function isInternalRcloneInstalled() {
|
||||||
|
console.log('[isInternalRcloneInstalled]')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const output = await Command.create('rclone-internal').execute()
|
const output = await Command.create('rclone-internal').execute()
|
||||||
// console.log('[isInternalRcloneInstalled] output', output)
|
// console.log('[isInternalRcloneInstalled] output', output)
|
||||||
@@ -74,18 +77,21 @@ export async function isInternalRcloneInstalled() {
|
|||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
export async function provisionRclone() {
|
export async function provisionRclone() {
|
||||||
|
console.log('[provisionRclone]')
|
||||||
|
|
||||||
const currentVersionString = await fetch('https://downloads.rclone.org/version.txt').then(
|
const currentVersionString = await fetch('https://downloads.rclone.org/version.txt').then(
|
||||||
(res) => res.text()
|
(res) => res.text()
|
||||||
)
|
)
|
||||||
console.log('currentVersionString', currentVersionString)
|
console.log('[provisionRclone] currentVersionString', currentVersionString)
|
||||||
|
|
||||||
const currentVersion = currentVersionString.split('v')?.[1]?.trim()
|
const currentVersion = currentVersionString.split('v')?.[1]?.trim()
|
||||||
|
|
||||||
if (!currentVersion) {
|
if (!currentVersion) {
|
||||||
console.error('Failed to get latest version')
|
console.error('[provisionRclone] failed to get latest version')
|
||||||
|
await message('Failed to get latest rclone version, please try again later.')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
console.log('currentVersion', currentVersion)
|
console.log('[provisionRclone] currentVersion', currentVersion)
|
||||||
|
|
||||||
const currentPlatform = platform()
|
const currentPlatform = platform()
|
||||||
console.log('currentPlatform', currentPlatform)
|
console.log('currentPlatform', currentPlatform)
|
||||||
@@ -97,29 +103,31 @@ export async function provisionRclone() {
|
|||||||
if (tempDirPath.endsWith('/') || tempDirPath.endsWith('\\')) {
|
if (tempDirPath.endsWith('/') || tempDirPath.endsWith('\\')) {
|
||||||
tempDirPath = tempDirPath.slice(0, -1)
|
tempDirPath = tempDirPath.slice(0, -1)
|
||||||
}
|
}
|
||||||
console.log('tempDirPath', tempDirPath)
|
console.log('[provisionRclone] tempDirPath', tempDirPath)
|
||||||
|
|
||||||
const arch = (await invoke('get_arch')) as 'arm64' | 'amd64' | '386' | 'unknown'
|
const arch = (await invoke('get_arch')) as 'arm64' | 'amd64' | '386' | 'unknown'
|
||||||
console.log('arch', arch)
|
console.log('[provisionRclone] arch', arch)
|
||||||
|
|
||||||
if (arch === 'unknown') {
|
if (arch === 'unknown') {
|
||||||
throw new Error('Failed to get architecture, please try again later.')
|
console.error('[provisionRclone] failed to get architecture')
|
||||||
|
await message('Failed to get current arch, please try again later.')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const downloadUrl = `https://downloads.rclone.org/v${currentVersion}/rclone-v${currentVersion}-${currentOs}-${arch}.zip`
|
const downloadUrl = `https://downloads.rclone.org/v${currentVersion}/rclone-v${currentVersion}-${currentOs}-${arch}.zip`
|
||||||
console.log('downloadUrl', downloadUrl)
|
console.log('[provisionRclone] downloadUrl', downloadUrl)
|
||||||
|
|
||||||
const downloadedFile = await fetch(downloadUrl).then((res) => res.arrayBuffer())
|
const downloadedFile = await fetch(downloadUrl).then((res) => res.arrayBuffer())
|
||||||
console.log('downloadedFile')
|
console.log('[provisionRclone] downloadedFile')
|
||||||
|
|
||||||
let tempDirExists
|
let tempDirExists
|
||||||
try {
|
try {
|
||||||
tempDirExists = await exists('rclone', {
|
tempDirExists = await exists('rclone', {
|
||||||
baseDir: BaseDirectory.Temp,
|
baseDir: BaseDirectory.Temp,
|
||||||
})
|
})
|
||||||
console.log('tempDirExists', tempDirExists)
|
console.log('[provisionRclone] tempDirExists', tempDirExists)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to check if rclone temp dir exists', error)
|
console.error('[provisionRclone] failed to check if rclone temp dir exists', error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tempDirExists) {
|
if (tempDirExists) {
|
||||||
@@ -128,9 +136,9 @@ export async function provisionRclone() {
|
|||||||
recursive: true,
|
recursive: true,
|
||||||
baseDir: BaseDirectory.Temp,
|
baseDir: BaseDirectory.Temp,
|
||||||
})
|
})
|
||||||
console.log('removed rclone temp dir')
|
console.log('[provisionRclone] removed rclone temp dir')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to remove rclone temp dir', error)
|
console.error('[provisionRclone] failed to remove rclone temp dir', error)
|
||||||
await message('Failed to provision rclone.')
|
await message('Failed to provision rclone.')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -140,21 +148,21 @@ export async function provisionRclone() {
|
|||||||
await mkdir('rclone', {
|
await mkdir('rclone', {
|
||||||
baseDir: BaseDirectory.Temp,
|
baseDir: BaseDirectory.Temp,
|
||||||
})
|
})
|
||||||
console.log('created rclone temp dir')
|
console.log('[provisionRclone] created rclone temp dir')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to create rclone temp dir', error)
|
console.error('[provisionRclone] failed to create rclone temp dir', error)
|
||||||
await message('Failed to provision rclone.')
|
await message('Failed to provision rclone.')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const zipPath = `${tempDirPath}/rclone/rclone-v${currentVersion}-${currentOs}-${arch}.zip`
|
const zipPath = `${tempDirPath}/rclone/rclone-v${currentVersion}-${currentOs}-${arch}.zip`
|
||||||
console.log('zipPath', zipPath)
|
console.log('[provisionRclone] zipPath', zipPath)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await writeFile(zipPath, new Uint8Array(downloadedFile))
|
await writeFile(zipPath, new Uint8Array(downloadedFile))
|
||||||
console.log('wrote zip file')
|
console.log('[provisionRclone] wrote zip file')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to write zip file', error)
|
console.error('[provisionRclone] failed to write zip file', error)
|
||||||
await message('Failed to provision rclone.')
|
await message('Failed to provision rclone.')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -164,48 +172,48 @@ export async function provisionRclone() {
|
|||||||
zipPath,
|
zipPath,
|
||||||
outputFolder: `${tempDirPath}/rclone/rclone-ui`,
|
outputFolder: `${tempDirPath}/rclone/rclone-ui`,
|
||||||
})
|
})
|
||||||
console.log('Successfully unzipped file')
|
console.log('[provisionRclone] successfully unzipped file')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to unzip file', error)
|
console.error('[provisionRclone] failed to unzip file', error)
|
||||||
await message('Failed to provision rclone.')
|
await message('Failed to provision rclone.')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const unarchivedPath = `${tempDirPath}/rclone/rclone-ui/rclone-v${currentVersion}-${currentOs}-${arch}`
|
const unarchivedPath = `${tempDirPath}/rclone/rclone-ui/rclone-v${currentVersion}-${currentOs}-${arch}`
|
||||||
console.log('unarchivedPath', unarchivedPath)
|
console.log('[provisionRclone] unarchivedPath', unarchivedPath)
|
||||||
|
|
||||||
const binaryName = currentPlatform === 'windows' ? 'rclone.exe' : 'rclone'
|
const binaryName = currentPlatform === 'windows' ? 'rclone.exe' : 'rclone'
|
||||||
|
|
||||||
// "/" here looks to be working on windows
|
// "/" here looks to be working on windows
|
||||||
const rcloneBinaryPath = unarchivedPath + '/' + binaryName
|
const rcloneBinaryPath = unarchivedPath + '/' + binaryName
|
||||||
console.log('rcloneBinaryPath', rcloneBinaryPath)
|
console.log('[provisionRclone] rcloneBinaryPath', rcloneBinaryPath)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const binaryExists = await exists(rcloneBinaryPath)
|
const binaryExists = await exists(rcloneBinaryPath)
|
||||||
console.log('rcloneBinaryPathExists', binaryExists)
|
console.log('[provisionRclone] rcloneBinaryPathExists', binaryExists)
|
||||||
if (!binaryExists) {
|
if (!binaryExists) {
|
||||||
throw new Error('Could not find rclone binary in zip')
|
throw new Error('Could not find rclone binary in zip')
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to check if rclone binary exists', error)
|
console.error('[provisionRclone] failed to check if rclone binary exists', error)
|
||||||
throw new Error('Could not find rclone binary in zip')
|
await message('Failed to provision rclone.')
|
||||||
}
|
}
|
||||||
|
|
||||||
const appLocalDataDirPath = await appLocalDataDir()
|
const appLocalDataDirPath = await appLocalDataDir()
|
||||||
console.log('appLocalDataDirPath', appLocalDataDirPath)
|
console.log('[provisionRclone] appLocalDataDirPath', appLocalDataDirPath)
|
||||||
|
|
||||||
const appLocalDataDirPathExists = await exists(appLocalDataDirPath)
|
const appLocalDataDirPathExists = await exists(appLocalDataDirPath)
|
||||||
console.log('appLocalDataDirPathExists', appLocalDataDirPathExists)
|
console.log('[provisionRclone] appLocalDataDirPathExists', appLocalDataDirPathExists)
|
||||||
|
|
||||||
if (!appLocalDataDirPathExists) {
|
if (!appLocalDataDirPathExists) {
|
||||||
await mkdir(appLocalDataDirPath, {
|
await mkdir(appLocalDataDirPath, {
|
||||||
recursive: true,
|
recursive: true,
|
||||||
})
|
})
|
||||||
console.log('appLocalDataDirPath created')
|
console.log('[provisionRclone] appLocalDataDirPath created')
|
||||||
}
|
}
|
||||||
|
|
||||||
await copyFile(rcloneBinaryPath, `${appLocalDataDirPath}/${binaryName}`)
|
await copyFile(rcloneBinaryPath, `${appLocalDataDirPath}/${binaryName}`)
|
||||||
console.log('copied rclone binary')
|
console.log('[provisionRclone] copied rclone binary')
|
||||||
|
|
||||||
const hasInstalled = await isInternalRcloneInstalled()
|
const hasInstalled = await isInternalRcloneInstalled()
|
||||||
|
|
||||||
@@ -213,5 +221,6 @@ export async function provisionRclone() {
|
|||||||
throw new Error('Failed to install rclone')
|
throw new Error('Failed to install rclone')
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('rclone has been installed')
|
console.log('[provisionRclone] rclone has been installed')
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-6
@@ -8,13 +8,15 @@ import { exit } from '@tauri-apps/plugin-process'
|
|||||||
import { Command } from '@tauri-apps/plugin-shell'
|
import { Command } from '@tauri-apps/plugin-shell'
|
||||||
|
|
||||||
export async function needsMountPlugin() {
|
export async function needsMountPlugin() {
|
||||||
|
console.log('[needsMountPlugin]')
|
||||||
|
|
||||||
const currentPlatform = platform()
|
const currentPlatform = platform()
|
||||||
if (currentPlatform === 'macos') {
|
if (currentPlatform === 'macos') {
|
||||||
// check fuse-t or osxfuse
|
// check fuse-t or osxfuse
|
||||||
const hasFuseT = await exists('/Library/Application Support/fuse-t')
|
const hasFuseT = await exists('/Library/Application Support/fuse-t')
|
||||||
console.log('hasFuseT', hasFuseT)
|
console.log('[needsMountPlugin] hasFuseT', hasFuseT)
|
||||||
const hasOsxFuse = await exists('/Library/Filesystems/macfuse.fs')
|
const hasOsxFuse = await exists('/Library/Filesystems/macfuse.fs')
|
||||||
console.log('hasOsxFuse', hasOsxFuse)
|
console.log('[needsMountPlugin] hasOsxFuse', hasOsxFuse)
|
||||||
return !hasFuseT && !hasOsxFuse
|
return !hasFuseT && !hasOsxFuse
|
||||||
}
|
}
|
||||||
if (currentPlatform === 'windows') {
|
if (currentPlatform === 'windows') {
|
||||||
@@ -22,13 +24,15 @@ export async function needsMountPlugin() {
|
|||||||
const hasWinFsp =
|
const hasWinFsp =
|
||||||
(await exists('C:\\Program Files\\WinFsp')) ||
|
(await exists('C:\\Program Files\\WinFsp')) ||
|
||||||
(await exists('C:\\Program Files (x86)\\WinFsp'))
|
(await exists('C:\\Program Files (x86)\\WinFsp'))
|
||||||
console.log('hasWinFsp', hasWinFsp)
|
console.log('[needsMountPlugin] hasWinFsp', hasWinFsp)
|
||||||
return !hasWinFsp
|
return !hasWinFsp
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function dialogGetMountPlugin() {
|
export async function dialogGetMountPlugin() {
|
||||||
|
console.log('[dialogGetMountPlugin]')
|
||||||
|
|
||||||
const currentPlatform = platform()
|
const currentPlatform = platform()
|
||||||
if (currentPlatform === 'macos') {
|
if (currentPlatform === 'macos') {
|
||||||
// download fuse-t or osxfuse
|
// download fuse-t or osxfuse
|
||||||
@@ -75,13 +79,12 @@ export async function dialogGetMountPlugin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function unmount(mountPoint: string, force = false) {
|
export async function unmount(mountPoint: string, force = false) {
|
||||||
|
console.log('[unmount]', mountPoint, force)
|
||||||
|
|
||||||
const command = Command.create('umount', [force ? '-f' : '', mountPoint])
|
const command = Command.create('umount', [force ? '-f' : '', mountPoint])
|
||||||
|
|
||||||
const output = await command.execute()
|
const output = await command.execute()
|
||||||
|
|
||||||
// console.log('output')
|
|
||||||
// console.log(JSON.stringify(output, null, 2))
|
|
||||||
|
|
||||||
if (output.code !== 0) {
|
if (output.code !== 0) {
|
||||||
if (output.stderr.toLowerCase().includes('busy')) {
|
if (output.stderr.toLowerCase().includes('busy')) {
|
||||||
const answer = await ask('This resource is busy, do you wish to force unmount?', {
|
const answer = await ask('This resource is busy, do you wish to force unmount?', {
|
||||||
@@ -97,9 +100,11 @@ export async function unmount(mountPoint: string, force = false) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (output.stderr.toLowerCase().includes('not currently mounted')) {
|
if (output.stderr.toLowerCase().includes('not currently mounted')) {
|
||||||
|
console.error('[unmount] not currently mounted')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.error('[unmount] failed to unmount', output.stderr)
|
||||||
throw new Error(output.stderr)
|
throw new Error(output.stderr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-8
@@ -24,19 +24,23 @@ export async function triggerTrayRebuild() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to update the tray menu
|
|
||||||
export async function rebuildTrayMenu() {
|
export async function rebuildTrayMenu() {
|
||||||
|
console.log('[rebuildTrayMenu]')
|
||||||
|
|
||||||
const tray = await getMainTray()
|
const tray = await getMainTray()
|
||||||
if (!tray) {
|
if (!tray) {
|
||||||
|
console.error('[rebuildTrayMenu] tray not found')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const newMenu = await buildMenu()
|
const newMenu = await buildMenu()
|
||||||
await tray.setMenu(newMenu)
|
await tray.setMenu(newMenu)
|
||||||
|
|
||||||
|
console.log('[rebuildTrayMenu] tray menu rebuilt')
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onTrayAction(event: TrayIconEvent) {
|
async function onTrayAction(event: TrayIconEvent) {
|
||||||
if (event.type === 'Click') {
|
if (event.type === 'Click') {
|
||||||
console.log('Tray clicked:', event)
|
console.log('[onTrayAction] tray clicked:', event)
|
||||||
|
|
||||||
await resetMainWindow()
|
await resetMainWindow()
|
||||||
}
|
}
|
||||||
@@ -45,12 +49,12 @@ async function onTrayAction(event: TrayIconEvent) {
|
|||||||
// Initialize the tray
|
// Initialize the tray
|
||||||
export async function initTray(): Promise<void> {
|
export async function initTray(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
console.log('initTray')
|
console.log('[initTray]')
|
||||||
const menu = await buildMenu()
|
const menu = await buildMenu()
|
||||||
console.log('built menu')
|
console.log('[initTray] built menu')
|
||||||
|
|
||||||
await TrayIcon.getById('loading-tray').then((t) => t?.setVisible(false))
|
await TrayIcon.getById('loading-tray').then((t) => t?.setVisible(false))
|
||||||
console.log('set loading tray to false')
|
console.log('[initTray] set loading tray to false')
|
||||||
|
|
||||||
await TrayIcon.new({
|
await TrayIcon.new({
|
||||||
id: 'main-tray',
|
id: 'main-tray',
|
||||||
@@ -61,13 +65,18 @@ export async function initTray(): Promise<void> {
|
|||||||
action: onTrayAction,
|
action: onTrayAction,
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to create tray')
|
console.error('[initTray] failed to create tray')
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function initLoadingTray() {
|
export async function initLoadingTray() {
|
||||||
if (platform() === 'linux') return
|
console.log('[initLoadingTray]')
|
||||||
|
|
||||||
|
if (platform() === 'linux') {
|
||||||
|
console.log('[initLoadingTray] platform is linux, skipping')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const globeIconPath = await resolveResource('icons/favicon/frame_00_delay-0.1s.png')
|
const globeIconPath = await resolveResource('icons/favicon/frame_00_delay-0.1s.png')
|
||||||
|
|
||||||
@@ -104,6 +113,6 @@ export async function initLoadingTray() {
|
|||||||
`icons/favicon/frame_${currentIcon < 10 ? '0' : ''}${currentIcon}_delay-0.1s.png`
|
`icons/favicon/frame_${currentIcon < 10 ? '0' : ''}${currentIcon}_delay-0.1s.png`
|
||||||
)
|
)
|
||||||
await loadingTray?.setIcon(globeIconPath)
|
await loadingTray?.setIcon(globeIconPath)
|
||||||
currentIcon = currentIcon + 1
|
currentIcon += 1
|
||||||
}, 200)
|
}, 200)
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-3
@@ -21,6 +21,8 @@ export async function openFullWindow({
|
|||||||
name: string
|
name: string
|
||||||
url: string
|
url: string
|
||||||
}) {
|
}) {
|
||||||
|
console.log('[openFullWindow]')
|
||||||
|
|
||||||
const w = new WebviewWindow(name, {
|
const w = new WebviewWindow(name, {
|
||||||
height: 0,
|
height: 0,
|
||||||
width: 0,
|
width: 0,
|
||||||
@@ -36,7 +38,10 @@ export async function openFullWindow({
|
|||||||
|
|
||||||
const size = await currentMonitor().then((m) => m?.size)
|
const size = await currentMonitor().then((m) => m?.size)
|
||||||
|
|
||||||
if (!size) return
|
if (!size) {
|
||||||
|
console.error('[openFullWindow] no monitor found')
|
||||||
|
throw new Error('No monitor found')
|
||||||
|
}
|
||||||
|
|
||||||
if (platform() === 'windows') {
|
if (platform() === 'windows') {
|
||||||
// windows merges the space for the taskbar
|
// windows merges the space for the taskbar
|
||||||
@@ -55,14 +60,16 @@ export async function openFullWindow({
|
|||||||
export async function openWindow({
|
export async function openWindow({
|
||||||
name,
|
name,
|
||||||
url,
|
url,
|
||||||
width = 740,
|
width = 820,
|
||||||
height = 600,
|
height = 700,
|
||||||
}: {
|
}: {
|
||||||
name: string
|
name: string
|
||||||
url: string
|
url: string
|
||||||
width?: number
|
width?: number
|
||||||
height?: number
|
height?: number
|
||||||
}) {
|
}) {
|
||||||
|
console.log('[openWindow]')
|
||||||
|
|
||||||
const isFirstWindow = useStore.getState().firstWindow
|
const isFirstWindow = useStore.getState().firstWindow
|
||||||
|
|
||||||
const w = new WebviewWindow(name, {
|
const w = new WebviewWindow(name, {
|
||||||
|
|||||||
@@ -86,9 +86,11 @@ async function validateInstance() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function startRclone() {
|
async function startRclone() {
|
||||||
|
console.log('[startRclone]')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const remotes = await listRemotes()
|
const remotes = await listRemotes()
|
||||||
console.log('rclone rcd already running')
|
console.log('[startRclone] rclone rcd already running')
|
||||||
useStore.setState({ rcloneLoaded: true })
|
useStore.setState({ rcloneLoaded: true })
|
||||||
useStore.setState({ remotes: remotes })
|
useStore.setState({ remotes: remotes })
|
||||||
return
|
return
|
||||||
@@ -99,7 +101,7 @@ async function startRclone() {
|
|||||||
try {
|
try {
|
||||||
rclone = await initRclone()
|
rclone = await initRclone()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await ask(error.message || 'Failed to provision rclone, please try again later.', {
|
await ask(error.message || 'Failed to start rclone, please try again later.', {
|
||||||
title: 'Error',
|
title: 'Error',
|
||||||
kind: 'error',
|
kind: 'error',
|
||||||
okLabel: 'Exit',
|
okLabel: 'Exit',
|
||||||
@@ -149,11 +151,12 @@ async function startRclone() {
|
|||||||
console.log('error', event)
|
console.log('error', event)
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log('running rclone')
|
console.log('[startRclone] starting rclone')
|
||||||
const childProcess = await command.spawn()
|
const childProcess = await command.spawn()
|
||||||
|
console.log('[startRclone] running rclone')
|
||||||
|
|
||||||
getCurrentWindow().listen('close-app', async (e) => {
|
getCurrentWindow().listen('close-app', async (e) => {
|
||||||
console.log('(main) window close-app requested')
|
console.log('[startRclone] (main) window close-app requested')
|
||||||
|
|
||||||
if (rclone.system) {
|
if (rclone.system) {
|
||||||
const answer = await ask('Unmount all remotes before exiting?', {
|
const answer = await ask('Unmount all remotes before exiting?', {
|
||||||
@@ -169,13 +172,15 @@ async function startRclone() {
|
|||||||
|
|
||||||
await childProcess.kill()
|
await childProcess.kill()
|
||||||
})
|
})
|
||||||
|
console.log('[startRclone] set listener for close-app')
|
||||||
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 200))
|
await new Promise((resolve) => setTimeout(resolve, 200))
|
||||||
|
|
||||||
useStore.setState({ rcloneLoaded: true })
|
useStore.setState({ rcloneLoaded: true })
|
||||||
|
|
||||||
|
console.log('[startRclone] listing remotes')
|
||||||
const remotes = await listRemotes()
|
const remotes = await listRemotes()
|
||||||
console.log('remotes', remotes)
|
console.log('[startRclone] got remotes')
|
||||||
useStore.setState({ remotes: remotes })
|
useStore.setState({ remotes: remotes })
|
||||||
|
|
||||||
// console.log('childProcess', JSON.stringify(childProcess)) // prints `pid`
|
// console.log('childProcess', JSON.stringify(childProcess)) // prints `pid`
|
||||||
@@ -210,6 +215,17 @@ async function startupMounts() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function onboardUser() {
|
||||||
|
const firstOpen = usePersistedStore.getState().isFirstOpen
|
||||||
|
if (firstOpen) {
|
||||||
|
await message('Rclone has initialized, you can now find it in the tray menu!', {
|
||||||
|
title: 'Welcome to Rclone UI',
|
||||||
|
kind: 'info',
|
||||||
|
okLabel: 'Got it',
|
||||||
|
})
|
||||||
|
usePersistedStore.setState({ isFirstOpen: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
getCurrentWindow().listen('tauri://close-requested', async (e) => {
|
getCurrentWindow().listen('tauri://close-requested', async (e) => {
|
||||||
console.log('(main) window close requested')
|
console.log('(main) window close requested')
|
||||||
})
|
})
|
||||||
@@ -235,17 +251,7 @@ initLoadingTray()
|
|||||||
.then(() => waitForHydration())
|
.then(() => waitForHydration())
|
||||||
.then(() => validateInstance())
|
.then(() => validateInstance())
|
||||||
.then(() => startRclone())
|
.then(() => startRclone())
|
||||||
.then(async () => {
|
.then(() => onboardUser())
|
||||||
const firstOpen = usePersistedStore.getState().isFirstOpen
|
|
||||||
if (firstOpen) {
|
|
||||||
await message('Rclone has initialized, you can now find it in the tray menu!', {
|
|
||||||
title: 'Welcome',
|
|
||||||
kind: 'info',
|
|
||||||
okLabel: 'Got it',
|
|
||||||
})
|
|
||||||
usePersistedStore.setState({ isFirstOpen: false })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(() => startupMounts())
|
.then(() => startupMounts())
|
||||||
.then(() => initTray())
|
.then(() => initTray())
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
|||||||
Generated
+3974
-2653
File diff suppressed because it is too large
Load Diff
+28
-25
@@ -19,42 +19,45 @@
|
|||||||
"build:wasm": "tauri build --target wasm32-unknown-unknown"
|
"build:wasm": "tauri build --target wasm32-unknown-unknown"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nextui-org/react": "^2.6.11",
|
"@heroui/react": "^2.7.11",
|
||||||
"@tauri-apps/api": "~2.2.0",
|
"@tauri-apps/api": "~2.7.0",
|
||||||
"@tauri-apps/plugin-autostart": "^2.2.0",
|
"@tauri-apps/plugin-autostart": "^2.5.0",
|
||||||
"@tauri-apps/plugin-dialog": "^2.2.0",
|
"@tauri-apps/plugin-dialog": "^2.3.2",
|
||||||
"@tauri-apps/plugin-fs": "^2.2.0",
|
"@tauri-apps/plugin-fs": "^2.4.1",
|
||||||
"@tauri-apps/plugin-http": "^2.2.0",
|
"@tauri-apps/plugin-http": "^2.5.1",
|
||||||
"@tauri-apps/plugin-log": "^2.2.0",
|
"@tauri-apps/plugin-log": "^2.6.0",
|
||||||
"@tauri-apps/plugin-notification": "^2.2.1",
|
"@tauri-apps/plugin-notification": "^2.3.0",
|
||||||
"@tauri-apps/plugin-opener": "^2.2.5",
|
"@tauri-apps/plugin-opener": "^2.4.0",
|
||||||
"@tauri-apps/plugin-os": "^2.2.0",
|
"@tauri-apps/plugin-os": "^2.3.0",
|
||||||
"@tauri-apps/plugin-process": "^2.2.0",
|
"@tauri-apps/plugin-process": "^2.3.0",
|
||||||
"@tauri-apps/plugin-shell": "^2.2.0",
|
"@tauri-apps/plugin-shell": "^2.3.0",
|
||||||
"@tauri-apps/plugin-store": "^2.2.0",
|
"@tauri-apps/plugin-store": "^2.3.0",
|
||||||
"@tauri-apps/plugin-updater": "^2.4.0",
|
"@tauri-apps/plugin-updater": "^2.9.0",
|
||||||
"@tauri-apps/plugin-window-state": "^2.2.0",
|
"@tauri-apps/plugin-window-state": "^2.4.0",
|
||||||
"framer-motion": "^11.17.0",
|
"cron-parser": "^5.3.0",
|
||||||
"lucide-react": "^0.471.0",
|
"cronstrue": "^3.2.0",
|
||||||
|
"date-fns": "^4.1.0",
|
||||||
|
"framer-motion": "^11.18.2",
|
||||||
|
"lucide-react": "^0.536.0",
|
||||||
"p-retry": "^6.2.1",
|
"p-retry": "^6.2.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-router-dom": "^6.28.1",
|
"react-router-dom": "^6.28.1",
|
||||||
"use-broadcast-ts": "^2.0.0",
|
"use-broadcast-ts": "^2.0.1",
|
||||||
"zustand": "^5.0.3"
|
"zustand": "^5.0.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^1.9.4",
|
"@biomejs/biome": "^1.9.4",
|
||||||
"@tauri-apps/cli": "~2.2.5",
|
"@tauri-apps/cli": "~2.7.1",
|
||||||
"@types/node": "^22.10.7",
|
"@types/node": "^22.10.7",
|
||||||
"@types/react": "^18.3.1",
|
"@types/react": "^18.3.1",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.7.0",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.21",
|
||||||
"esbuild": "^0.24.2",
|
"esbuild": "^0.25.8",
|
||||||
"postcss": "^8.4.49",
|
"postcss": "^8.5.6",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "~5.6.2",
|
"typescript": "~5.6.2",
|
||||||
"vite": "^6.0.3"
|
"vite": "^6.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+609
-421
File diff suppressed because it is too large
Load Diff
+14
-14
@@ -21,25 +21,25 @@ tauri-build = { version = "2.0.4", features = [] }
|
|||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
tauri = { version = "2.2.0", features = [ "tray-icon", "image-ico",
|
tauri = { version = "2.7.0", features = [ "tray-icon", "image-ico",
|
||||||
"image-png", "config-json5" ] }
|
"image-png", "config-json5" ] }
|
||||||
tauri-plugin-log = "2.2.0"
|
tauri-plugin-log = "2.6.0"
|
||||||
tauri-plugin-shell = "2.2.0"
|
tauri-plugin-shell = "2.3.0"
|
||||||
tauri-plugin-dialog = "2.2.0"
|
tauri-plugin-dialog = "2.3.2"
|
||||||
tauri-plugin-fs = "2.2.0"
|
tauri-plugin-fs = "2.4.1"
|
||||||
tauri-plugin-opener = "2.2.3"
|
tauri-plugin-opener = "2.4.0"
|
||||||
tauri-plugin-http = "2.2.0"
|
tauri-plugin-http = "2.5.1"
|
||||||
tauri-plugin-store = "2.2.0"
|
tauri-plugin-store = "2.3.0"
|
||||||
tauri-plugin-process = "2"
|
tauri-plugin-process = "2.3.0"
|
||||||
tauri-plugin-notification = { version = "2.0.0", features = [ "windows7-compat" ] }
|
tauri-plugin-notification = { version = "2.3.0", features = [ "windows7-compat" ] }
|
||||||
tauri-plugin-os = "2"
|
tauri-plugin-os = "2.3.0"
|
||||||
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"
|
zip = "0.6.6"
|
||||||
machine-uid = "0.5.3"
|
machine-uid = "0.5.3"
|
||||||
tauri-plugin-sentry = "0.4.1"
|
tauri-plugin-sentry = "0.4.1"
|
||||||
tauri-plugin-autostart = "2"
|
tauri-plugin-autostart = "2.5.0"
|
||||||
tauri-plugin-single-instance = "2.2.0"
|
tauri-plugin-single-instance = "2.3.2"
|
||||||
tauri-plugin-updater = "2"
|
tauri-plugin-updater = "2.9.0"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
cocoa = "0.26"
|
cocoa = "0.26"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Chip, Textarea, Tooltip } from '@nextui-org/react'
|
import { Chip, Textarea, Tooltip } from '@heroui/react'
|
||||||
import { LockKeyholeIcon, LockOpenIcon, XIcon } from 'lucide-react'
|
import { LockKeyholeIcon, LockOpenIcon, XIcon } from 'lucide-react'
|
||||||
import { useCallback, useEffect, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
import { replaceSmartQuotes } from '../../lib/format'
|
import { replaceSmartQuotes } from '../../lib/format'
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Autocomplete } from '@nextui-org/autocomplete'
|
import { Autocomplete, Tooltip } from '@heroui/react'
|
||||||
import { AutocompleteItem, Button } from '@nextui-org/react'
|
import { AutocompleteItem, Button } from '@heroui/react'
|
||||||
|
import { cn } from '@heroui/react'
|
||||||
import { open } from '@tauri-apps/plugin-dialog'
|
import { open } from '@tauri-apps/plugin-dialog'
|
||||||
import { readDir } from '@tauri-apps/plugin-fs'
|
import { readDir } from '@tauri-apps/plugin-fs'
|
||||||
import { platform } from '@tauri-apps/plugin-os'
|
import { platform } from '@tauri-apps/plugin-os'
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Drawer, DrawerBody, DrawerFooter, DrawerHeader } from '@nextui-org/drawer'
|
import { Drawer, DrawerBody, DrawerFooter, DrawerHeader } from '@heroui/react'
|
||||||
import {
|
import {
|
||||||
Autocomplete,
|
Autocomplete,
|
||||||
AutocompleteItem,
|
AutocompleteItem,
|
||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
Select,
|
Select,
|
||||||
SelectItem,
|
SelectItem,
|
||||||
} from '@nextui-org/react'
|
} from '@heroui/react'
|
||||||
import { message } from '@tauri-apps/plugin-dialog'
|
import { message } from '@tauri-apps/plugin-dialog'
|
||||||
import { ChevronDown, ChevronUp, RefreshCcwIcon } from 'lucide-react'
|
import { ChevronDown, ChevronUp, RefreshCcwIcon } from 'lucide-react'
|
||||||
import { useEffect, useMemo, useState } from 'react'
|
import { useEffect, useMemo, useState } from 'react'
|
||||||
@@ -73,20 +73,6 @@ export default function RemoteCreateDrawer({
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
// <input
|
|
||||||
// type="checkbox"
|
|
||||||
// id={fieldId}
|
|
||||||
// name={option.Name}
|
|
||||||
// className="form-checkbox"
|
|
||||||
// defaultChecked={fieldValue === 'true'}
|
|
||||||
// onChange={(e) =>
|
|
||||||
// setConfig({ ...config, [option.Name]: e.target.checked })
|
|
||||||
// }
|
|
||||||
// autoComplete="off"
|
|
||||||
// autoCapitalize="off"
|
|
||||||
// autoCorrect="off"
|
|
||||||
// spellCheck={false}
|
|
||||||
// />
|
|
||||||
)
|
)
|
||||||
case 'string': {
|
case 'string': {
|
||||||
if (option.Examples && option.Examples.length > 0) {
|
if (option.Examples && option.Examples.length > 0) {
|
||||||
@@ -127,7 +113,7 @@ export default function RemoteCreateDrawer({
|
|||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCapitalize="off"
|
autoCapitalize="off"
|
||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
spellCheck={false}
|
spellCheck="false"
|
||||||
description={option.Help.split('\n').slice(1).join('\n')}
|
description={option.Help.split('\n').slice(1).join('\n')}
|
||||||
isRequired={option.Required}
|
isRequired={option.Required}
|
||||||
onValueChange={(value) => {
|
onValueChange={(value) => {
|
||||||
@@ -136,37 +122,6 @@ export default function RemoteCreateDrawer({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
// if (option.Examples && option.Examples.length > 0) {
|
|
||||||
// return (
|
|
||||||
// <select
|
|
||||||
// id={fieldId}
|
|
||||||
// name={option.Name}
|
|
||||||
// className="w-full p-2 border rounded dark:bg-gray-800"
|
|
||||||
// value={fieldValue}
|
|
||||||
// onChange={(e) =>
|
|
||||||
// setConfig({ ...config, [option.Name]: e.target.value })
|
|
||||||
// }
|
|
||||||
// >
|
|
||||||
// <option value="">Select {option.Name}</option>
|
|
||||||
// {option.Examples.map((example) => (
|
|
||||||
// <option key={example.Value} value={example.Value}>
|
|
||||||
// {example.Help || example.Value}
|
|
||||||
// </option>
|
|
||||||
// ))}
|
|
||||||
// </select>
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// return (
|
|
||||||
// <input
|
|
||||||
// id={fieldId}
|
|
||||||
// name={option.Name}
|
|
||||||
// type={option.IsPassword ? 'password' : 'text'}
|
|
||||||
// value={fieldValue || ''}
|
|
||||||
// onChange={(e) =>
|
|
||||||
// setConfig({ ...config, [option.Name]: e.target.value })
|
|
||||||
// }
|
|
||||||
// />
|
|
||||||
// )
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
@@ -275,7 +230,7 @@ export default function RemoteCreateDrawer({
|
|||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCapitalize="off"
|
autoCapitalize="off"
|
||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
spellCheck={false}
|
spellCheck="false"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
@@ -290,7 +245,7 @@ export default function RemoteCreateDrawer({
|
|||||||
isRequired={true}
|
isRequired={true}
|
||||||
>
|
>
|
||||||
{backends.map((backend) => (
|
{backends.map((backend) => (
|
||||||
<SelectItem key={backend.Name} value={backend.Name}>
|
<SelectItem key={backend.Name}>
|
||||||
{backend.Description.includes('Compliant')
|
{backend.Description.includes('Compliant')
|
||||||
? `${backend.Description.split('Compliant')[0]} Compliant`
|
? `${backend.Description.split('Compliant')[0]} Compliant`
|
||||||
: backend.Description || backend.Name}
|
: backend.Description || backend.Name}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Checkbox } from '@nextui-org/checkbox'
|
import { Checkbox } from '@heroui/react'
|
||||||
import { Drawer, DrawerBody, DrawerContent, DrawerFooter, DrawerHeader } from '@nextui-org/drawer'
|
import { Drawer, DrawerBody, DrawerContent, DrawerFooter, DrawerHeader } from '@heroui/react'
|
||||||
import { Accordion, AccordionItem, Avatar, Button, Input } from '@nextui-org/react'
|
import { Accordion, AccordionItem, Avatar, Button, Input } from '@heroui/react'
|
||||||
import { homeDir } from '@tauri-apps/api/path'
|
import { homeDir } from '@tauri-apps/api/path'
|
||||||
import { message, open } from '@tauri-apps/plugin-dialog'
|
import { message, open } from '@tauri-apps/plugin-dialog'
|
||||||
import {
|
import {
|
||||||
@@ -82,7 +82,6 @@ export default function RemoteDefaultsDrawer({
|
|||||||
const handleSubmit = useCallback(async () => {
|
const handleSubmit = useCallback(async () => {
|
||||||
if (!config) {
|
if (!config) {
|
||||||
console.log('No config')
|
console.log('No config')
|
||||||
// console.log(JSON.stringify(config, null, 2))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +308,7 @@ export default function RemoteDefaultsDrawer({
|
|||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCapitalize="off"
|
autoCapitalize="off"
|
||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
spellCheck={false}
|
spellCheck="false"
|
||||||
onValueChange={(value) => {
|
onValueChange={(value) => {
|
||||||
setConfig((prev) => ({
|
setConfig((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
@@ -330,7 +329,7 @@ export default function RemoteDefaultsDrawer({
|
|||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCapitalize="off"
|
autoCapitalize="off"
|
||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
spellCheck={false}
|
spellCheck="false"
|
||||||
startContent={
|
startContent={
|
||||||
<Button
|
<Button
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
@@ -340,6 +339,7 @@ export default function RemoteDefaultsDrawer({
|
|||||||
directory: true,
|
directory: true,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
defaultPath: await homeDir(),
|
defaultPath: await homeDir(),
|
||||||
|
title: 'Select a mount point',
|
||||||
})
|
})
|
||||||
await unlockWindows()
|
await unlockWindows()
|
||||||
if (selected) {
|
if (selected) {
|
||||||
@@ -511,14 +511,6 @@ export default function RemoteDefaultsDrawer({
|
|||||||
rows={20}
|
rows={20}
|
||||||
/>
|
/>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
{/* <SyncSection
|
|
||||||
remoteName={remoteName}
|
|
||||||
syncOptionsJson={syncOptionsJson}
|
|
||||||
setSyncOptionsJson={setSyncOptionsJson}
|
|
||||||
globalOptions={
|
|
||||||
globalOptions['main' as keyof typeof globalOptions]
|
|
||||||
}
|
|
||||||
/> */}
|
|
||||||
</Accordion>
|
</Accordion>
|
||||||
</DrawerBody>
|
</DrawerBody>
|
||||||
<DrawerFooter>
|
<DrawerFooter>
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
import { Checkbox } from '@nextui-org/checkbox'
|
import { Checkbox } from '@heroui/react'
|
||||||
import { Drawer, DrawerBody, DrawerContent, DrawerFooter, DrawerHeader } from '@nextui-org/drawer'
|
import { Drawer, DrawerBody, DrawerContent, DrawerFooter, DrawerHeader } from '@heroui/react'
|
||||||
import {
|
import { Autocomplete, AutocompleteItem, Button, Input, Select, SelectItem } from '@heroui/react'
|
||||||
Autocomplete,
|
|
||||||
AutocompleteItem,
|
|
||||||
Button,
|
|
||||||
Input,
|
|
||||||
Select,
|
|
||||||
SelectItem,
|
|
||||||
} from '@nextui-org/react'
|
|
||||||
import { message } from '@tauri-apps/plugin-dialog'
|
import { message } from '@tauri-apps/plugin-dialog'
|
||||||
import { ChevronDown, ChevronUp } from 'lucide-react'
|
import { ChevronDown, ChevronUp } from 'lucide-react'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
@@ -115,7 +108,7 @@ export default function RemoteEditDrawer({
|
|||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCapitalize="off"
|
autoCapitalize="off"
|
||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
spellCheck={false}
|
spellCheck="false"
|
||||||
description={option.Help.split('\n').slice(1).join('\n')}
|
description={option.Help.split('\n').slice(1).join('\n')}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@@ -204,14 +197,10 @@ export default function RemoteEditDrawer({
|
|||||||
selectionMode="single"
|
selectionMode="single"
|
||||||
placeholder="Select Type"
|
placeholder="Select Type"
|
||||||
selectedKeys={[config.type]}
|
selectedKeys={[config.type]}
|
||||||
// onChange={(e) => {
|
|
||||||
// console.log(e.target.value)
|
|
||||||
// setConfig({ ...config, type: e.target.value })
|
|
||||||
// }}
|
|
||||||
isDisabled={true}
|
isDisabled={true}
|
||||||
>
|
>
|
||||||
{backends.map((backend) => (
|
{backends.map((backend) => (
|
||||||
<SelectItem key={backend.Name} value={backend.Name}>
|
<SelectItem key={backend.Name}>
|
||||||
{backend.Description.includes('Compliant')
|
{backend.Description.includes('Compliant')
|
||||||
? `${backend.Description.split('Compliant')[0]} Compliant`
|
? `${backend.Description.split('Compliant')[0]} Compliant`
|
||||||
: backend.Description || backend.Name}
|
: backend.Description || backend.Name}
|
||||||
|
|||||||
+3
-3
@@ -3,7 +3,7 @@ import ReactDOM from 'react-dom/client'
|
|||||||
import { RouterProvider, createBrowserRouter } from 'react-router-dom'
|
import { RouterProvider, createBrowserRouter } from 'react-router-dom'
|
||||||
import Home from './pages/Home'
|
import Home from './pages/Home'
|
||||||
import './global.css'
|
import './global.css'
|
||||||
import { NextUIProvider } from '@nextui-org/react'
|
import { HeroUIProvider } from '@heroui/react'
|
||||||
import { debug, error, info, trace, warn } from '@tauri-apps/plugin-log'
|
import { debug, error, info, trace, warn } from '@tauri-apps/plugin-log'
|
||||||
import Copy from './pages/Copy'
|
import Copy from './pages/Copy'
|
||||||
import Jobs from './pages/Jobs'
|
import Jobs from './pages/Jobs'
|
||||||
@@ -64,9 +64,9 @@ const router = createBrowserRouter([
|
|||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<NextUIProvider>
|
<HeroUIProvider>
|
||||||
{/* <TauriWatcher /> */}
|
{/* <TauriWatcher /> */}
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
</NextUIProvider>
|
</HeroUIProvider>
|
||||||
</React.StrictMode>
|
</React.StrictMode>
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Accordion, AccordionItem, Avatar, Button } from '@nextui-org/react'
|
import { Accordion, AccordionItem, Avatar, Button } from '@heroui/react'
|
||||||
import { message } from '@tauri-apps/plugin-dialog'
|
import { message } from '@tauri-apps/plugin-dialog'
|
||||||
import { exists } from '@tauri-apps/plugin-fs'
|
import { exists } from '@tauri-apps/plugin-fs'
|
||||||
import { AlertOctagonIcon, CopyIcon, FilterIcon, FoldersIcon, PlayIcon } from 'lucide-react'
|
import { AlertOctagonIcon, CopyIcon, FilterIcon, FoldersIcon, PlayIcon } from 'lucide-react'
|
||||||
|
|||||||
+3
-3
@@ -1,5 +1,5 @@
|
|||||||
import { Card, CardBody, CardFooter, CardHeader } from '@nextui-org/card'
|
import { Card, CardBody, CardFooter, CardHeader } from '@heroui/react'
|
||||||
import { Button, Chip, Divider, Progress, Spinner } from '@nextui-org/react'
|
import { Button, Chip, Divider, Progress, Spinner } from '@heroui/react'
|
||||||
import { listen } from '@tauri-apps/api/event'
|
import { listen } from '@tauri-apps/api/event'
|
||||||
import { ask } from '@tauri-apps/plugin-dialog'
|
import { ask } from '@tauri-apps/plugin-dialog'
|
||||||
import { Trash2Icon } from 'lucide-react'
|
import { Trash2Icon } from 'lucide-react'
|
||||||
@@ -50,7 +50,7 @@ export default function Jobs() {
|
|||||||
await fetchJobs()
|
await fetchJobs()
|
||||||
}, 2000)
|
}, 2000)
|
||||||
|
|
||||||
//! prevents jobs being refreshed after "X" was pressed on the window
|
// prevents jobs being refreshed after closing the window
|
||||||
const unlisten = listen('tauri://close-requested', () => {
|
const unlisten = listen('tauri://close-requested', () => {
|
||||||
clearInterval(interval)
|
clearInterval(interval)
|
||||||
})
|
})
|
||||||
|
|||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
import { Accordion, AccordionItem, Avatar, Button } from '@nextui-org/react'
|
import { Accordion, AccordionItem, Avatar, Button } from '@heroui/react'
|
||||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||||
import { message } from '@tauri-apps/plugin-dialog'
|
import { message } from '@tauri-apps/plugin-dialog'
|
||||||
import { exists, mkdir, remove } from '@tauri-apps/plugin-fs'
|
import { exists, mkdir, remove } from '@tauri-apps/plugin-fs'
|
||||||
@@ -201,7 +201,7 @@ export default function Mount() {
|
|||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-screen gap-10 pt-10">
|
<div className="flex flex-col h-screen gap-10 pt-10">
|
||||||
{/* Main Content */}
|
{/* Main Content */}
|
||||||
<div className="flex flex-col flex-1 w-full max-w-xl gap-6 mx-auto">
|
<div className="flex flex-col flex-1 w-full max-w-3xl gap-6 mx-auto">
|
||||||
{/* Paths Display */}
|
{/* Paths Display */}
|
||||||
<PathFinder
|
<PathFinder
|
||||||
sourcePath={source}
|
sourcePath={source}
|
||||||
@@ -240,7 +240,7 @@ export default function Mount() {
|
|||||||
setOptionsJson={setMountOptionsJson}
|
setOptionsJson={setMountOptionsJson}
|
||||||
globalOptions={globalOptions['mount' as keyof typeof globalOptions]}
|
globalOptions={globalOptions['mount' as keyof typeof globalOptions]}
|
||||||
optionsFetcher={getMountFlags}
|
optionsFetcher={getMountFlags}
|
||||||
rows={5}
|
rows={7}
|
||||||
isLocked={mountOptionsLocked}
|
isLocked={mountOptionsLocked}
|
||||||
setIsLocked={setMountOptionsLocked}
|
setIsLocked={setMountOptionsLocked}
|
||||||
/>
|
/>
|
||||||
|
|||||||
+8
-28
@@ -1,4 +1,4 @@
|
|||||||
import { Button, Card, CardBody, Checkbox, Chip, Input, Tab, Tabs } from '@nextui-org/react'
|
import { Button, Card, CardBody, Checkbox, Chip, Input, Tab, Tabs } from '@heroui/react'
|
||||||
import { ask, message } from '@tauri-apps/plugin-dialog'
|
import { ask, message } from '@tauri-apps/plugin-dialog'
|
||||||
import { openUrl } from '@tauri-apps/plugin-opener'
|
import { openUrl } from '@tauri-apps/plugin-opener'
|
||||||
import { relaunch } from '@tauri-apps/plugin-process'
|
import { relaunch } from '@tauri-apps/plugin-process'
|
||||||
@@ -38,7 +38,7 @@ function Settings() {
|
|||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
spellCheck={false}
|
spellCheck="false"
|
||||||
type={passwordVisible ? 'text' : 'password'}
|
type={passwordVisible ? 'text' : 'password'}
|
||||||
fullWidth={false}
|
fullWidth={false}
|
||||||
size="lg"
|
size="lg"
|
||||||
@@ -75,20 +75,22 @@ function Settings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col w-screen h-screen gap-0 overflow-hidden animate-fade-in">
|
<div className="relative flex flex-col w-screen h-screen gap-0 overflow-hidden">
|
||||||
<Tabs
|
<Tabs
|
||||||
aria-label="Options"
|
aria-label="Options"
|
||||||
isVertical={true}
|
isVertical={true}
|
||||||
variant="light"
|
variant="light"
|
||||||
destroyInactiveTabPanel={false}
|
destroyInactiveTabPanel={false}
|
||||||
disableAnimation={true}
|
disableAnimation={true}
|
||||||
className="flex-shrink-0 w-3/12 h-screen px-2 py-4 border-r border-neutral-700"
|
className="flex-shrink-0 w-40 h-screen px-2 py-4 border-r border-neutral-700"
|
||||||
classNames={{
|
classNames={{
|
||||||
tabList: 'w-full gap-3',
|
tabList: 'w-full gap-3',
|
||||||
|
tab: 'h-14',
|
||||||
}}
|
}}
|
||||||
size="lg"
|
size="lg"
|
||||||
defaultSelectedKey="general"
|
defaultSelectedKey="general"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
|
radius="sm"
|
||||||
>
|
>
|
||||||
<Tab
|
<Tab
|
||||||
key="general"
|
key="general"
|
||||||
@@ -276,7 +278,7 @@ function GeneralSection() {
|
|||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
spellCheck={false}
|
spellCheck="false"
|
||||||
type={passwordVisible ? 'text' : 'password'}
|
type={passwordVisible ? 'text' : 'password'}
|
||||||
endContent={
|
endContent={
|
||||||
passwordInput && (
|
passwordInput && (
|
||||||
@@ -454,7 +456,7 @@ function LicenseSection() {
|
|||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
spellCheck={false}
|
spellCheck="false"
|
||||||
endContent={
|
endContent={
|
||||||
licenseValid && <CheckIcon className="w-5 h-5 text-green-500" />
|
licenseValid && <CheckIcon className="w-5 h-5 text-green-500" />
|
||||||
}
|
}
|
||||||
@@ -806,25 +808,3 @@ function BaseHeader({ title, endContent }: { title: string; endContent?: React.R
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default Settings
|
export default Settings
|
||||||
|
|
||||||
// {/* <Button
|
|
||||||
// onPress={async () => {
|
|
||||||
// const enabled = await isEnabled()
|
|
||||||
// if (enabled) {
|
|
||||||
// await disable()
|
|
||||||
// } else {
|
|
||||||
// await enable()
|
|
||||||
// }
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// Start on boot
|
|
||||||
// </Button>
|
|
||||||
|
|
||||||
// <Button
|
|
||||||
// onPress={async () => {
|
|
||||||
// const enabled = await isEnabled()
|
|
||||||
// alert(enabled ? 'Enabled' : 'Disabled')
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// Get status
|
|
||||||
// </Button> */}
|
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
import { Accordion, AccordionItem, Avatar, Button } from '@nextui-org/react'
|
import { Accordion, AccordionItem, Avatar, Button } from '@heroui/react'
|
||||||
import { message } from '@tauri-apps/plugin-dialog'
|
import { message } from '@tauri-apps/plugin-dialog'
|
||||||
import { exists } from '@tauri-apps/plugin-fs'
|
import { exists } from '@tauri-apps/plugin-fs'
|
||||||
import { AlertOctagonIcon, FilterIcon, FolderSyncIcon, FoldersIcon, PlayIcon } from 'lucide-react'
|
import { AlertOctagonIcon, FilterIcon, FolderSyncIcon, FoldersIcon, PlayIcon } from 'lucide-react'
|
||||||
@@ -188,7 +188,7 @@ export default function Sync() {
|
|||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-screen gap-10 pt-10">
|
<div className="flex flex-col h-screen gap-10 pt-10">
|
||||||
{/* Main Content */}
|
{/* Main Content */}
|
||||||
<div className="flex flex-col flex-1 w-full max-w-xl gap-6 mx-auto">
|
<div className="flex flex-col flex-1 w-full max-w-3xl gap-6 mx-auto">
|
||||||
{/* Paths Display */}
|
{/* Paths Display */}
|
||||||
<PathFinder
|
<PathFinder
|
||||||
sourcePath={source}
|
sourcePath={source}
|
||||||
|
|||||||
+3
-3
@@ -1,14 +1,14 @@
|
|||||||
const { nextui } = require('@nextui-org/react')
|
const { heroui } = require('@heroui/react')
|
||||||
|
|
||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
export default {
|
export default {
|
||||||
content: [
|
content: [
|
||||||
'./index.html',
|
'./index.html',
|
||||||
'./src/**/*.{js,ts,jsx,tsx}',
|
'./src/**/*.{js,ts,jsx,tsx}',
|
||||||
'./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}',
|
'./node_modules/@heroui/theme/dist/**/*.{js,ts,jsx,tsx}',
|
||||||
],
|
],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {},
|
||||||
},
|
},
|
||||||
plugins: [nextui()],
|
plugins: [heroui()],
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user