can’t innovate my ass 

Signed-off-by: FTCHD <144691102+FTCHD@users.noreply.github.com>
This commit is contained in:
FTCHD
2025-12-07 18:42:44 +01:00
committed by GitHub
parent 4254efe732
commit 7a62659323
243 changed files with 20668 additions and 11553 deletions
+1289
View File
File diff suppressed because it is too large Load Diff
+98
View File
@@ -0,0 +1,98 @@
import type { ToolbarCommandId } from './types'
const COPY_DESCRIPTION =
'Copy files from a source to a destination without deleting destination files.'
const MOVE_DESCRIPTION =
'Move files from a source to a destination and delete them from the source.'
const SYNC_DESCRIPTION =
'Sync source to destination, updating existing files and removing stale ones.'
const MOUNT_DESCRIPTION = 'Mount a remote to the local filesystem with VFS options.'
const DOWNLOAD_DESCRIPTION = 'Download a URL directly into a remote or local path.'
const SERVE_DESCRIPTION = 'Serve a remote over HTTP, WebDAV, SFTP, FTP and Restic.'
const BISYNC_DESCRIPTION = 'Bi-directional sync keeping source and destination in parity.'
const DELETE_DESCRIPTION = 'Delete files or folders from a remote or local path.'
const PURGE_DESCRIPTION = 'Purge an entire path from a remote, deleting everything.'
const CLEANUP_DESCRIPTION = 'Cleanup a remote by removing trashed and partial files.'
const BROWSE_DESCRIPTION = 'Browse files and folders in a remote.'
const SETTINGS_DESCRIPTION = 'Open the Settings screen.'
const GITHUB_DESCRIPTION = 'Open an issue or check out the GitHub repository.'
const TRANSFERS_DESCRIPTION = 'Open the Transfers screen.'
const SCHEDULES_DESCRIPTION = 'Open the Schedules screen.'
const TEMPLATES_DESCRIPTION = 'Open the Templates screen.'
const REMOTE_CREATE_DESCRIPTION = 'Create a new remote.'
const REMOTE_EDIT_DESCRIPTION = 'Edit a remote.'
const REMOTE_AUTO_MOUNT_DESCRIPTION = 'Configure auto mount options for a remote.'
const REMOTE_LIST_DESCRIPTION = 'Show all configured remotes.'
const QUIT_DESCRIPTION = 'Quit the application.'
export const COMMAND_CONFIG = {
copy: { route: '/copy', windowLabel: 'Copy' },
move: { route: '/move', windowLabel: 'Move' },
sync: { route: '/sync', windowLabel: 'Sync' },
mount: { route: '/mount', windowLabel: 'Mount' },
download: { route: '/download', windowLabel: 'Download' },
serve: { route: '/serve', windowLabel: 'Serve' },
bisync: { route: '/bisync', windowLabel: 'Bisync' },
delete: { route: '/delete', windowLabel: 'Delete' },
purge: { route: '/purge', windowLabel: 'Purge' },
cleanup: {},
browse: {},
settings: { route: '/settings', windowLabel: 'Settings' },
github: { route: '/github', windowLabel: 'GitHub' },
transfers: { route: '/transfers', windowLabel: 'Transfers' },
schedules: { route: '/schedules', windowLabel: 'Schedules' },
templates: { route: '/templates', windowLabel: 'Templates' },
remoteCreate: {},
remoteEdit: {},
remoteAutoMount: {},
remoteList: {},
quit: {},
} as const
export const COMMAND_DESCRIPTIONS: Record<ToolbarCommandId, string> = {
copy: COPY_DESCRIPTION,
move: MOVE_DESCRIPTION,
sync: SYNC_DESCRIPTION,
mount: MOUNT_DESCRIPTION,
download: DOWNLOAD_DESCRIPTION,
serve: SERVE_DESCRIPTION,
bisync: BISYNC_DESCRIPTION,
delete: DELETE_DESCRIPTION,
purge: PURGE_DESCRIPTION,
cleanup: CLEANUP_DESCRIPTION,
browse: BROWSE_DESCRIPTION,
settings: SETTINGS_DESCRIPTION,
github: GITHUB_DESCRIPTION,
transfers: TRANSFERS_DESCRIPTION,
schedules: SCHEDULES_DESCRIPTION,
templates: TEMPLATES_DESCRIPTION,
remoteCreate: REMOTE_CREATE_DESCRIPTION,
remoteEdit: REMOTE_EDIT_DESCRIPTION,
remoteAutoMount: REMOTE_AUTO_MOUNT_DESCRIPTION,
remoteList: REMOTE_LIST_DESCRIPTION,
quit: QUIT_DESCRIPTION,
}
export const COMMAND_KEYWORDS: Record<ToolbarCommandId, string[]> = {
copy: ['copy', 'cp', 'transfer'],
move: ['move', 'mv'],
sync: ['sync', 'synchronise', 'synchronize'],
mount: ['mount'],
download: ['download', 'url', 'copyurl', 'copyto'],
serve: ['serve', 'http', 'webdav', 'sftp', 'ftp', 'restic'],
bisync: ['bisync'],
delete: ['delete', 'remove', 'rm'],
purge: ['purge', 'empty'],
cleanup: ['cleanup', 'clean'],
browse: ['browse', 'explore', 'open', 'view', 'files'],
settings: ['settings', 'config', 'preferences'],
github: ['github', 'issue', 'bug', 'feature'],
transfers: ['transfer', 'job', 'task'],
schedules: ['schedule', 'cron', 'task'],
templates: ['template', 'example'],
remoteCreate: ['new', 'remote', 'create'],
remoteEdit: ['edit', 'remote', 'update', 'change'],
remoteAutoMount: ['mount', 'remote', 'update', 'change'],
remoteList: ['remote', 'list', 'show'],
quit: ['quit', 'exit', 'close'],
}
+288
View File
@@ -0,0 +1,288 @@
import { sep } from '@tauri-apps/api/path'
import { getToolbarAction, getToolbarActions } from './actions'
import type {
ToolbarActionArgs,
ToolbarActionContext,
ToolbarActionDefinition,
ToolbarActionPath,
ToolbarActionResult,
ToolbarCommandId,
} from './types'
export interface ResolvedToolbarResult {
id: string
actionId: ToolbarCommandId
label: string
description?: string
args: ToolbarActionArgs
score: number
resolve: () => ToolbarActionDefinition
}
export function runToolbarEngine(
query: string,
remotes: string[],
remoteTypes?: Record<string, string>
) {
const actions = getToolbarActions()
const trimmed = query.trim()
const parsedPaths = extractPaths(trimmed, remotes, remoteTypes)
const cleanedQuery = trimmed.replace(parsedPaths.map((path) => path.full).join(' '), '').trim()
const results = trimmed
? collectActionResults(actions, {
query: cleanedQuery,
fullQuery: trimmed,
paths: parsedPaths,
})
: buildDefaultResults(actions, remotes)
const finalResults = results.length > 0 ? results : buildDefaultResults(actions, remotes)
return {
results: finalResults.sort((a, b) => b.score - a.score),
}
}
function collectActionResults(
actions: ToolbarActionDefinition[],
context: ToolbarActionContext
): ResolvedToolbarResult[] {
const collected: ResolvedToolbarResult[] = []
for (const action of actions) {
const results = action.getResults(context)
for (const result of results) {
collected.push(mapResult(action, result))
}
}
return dedupeResults(collected)
}
function buildDefaultResults(
actions: ToolbarActionDefinition[],
remotes: string[]
): ResolvedToolbarResult[] {
return actions
.map((action) =>
action.getDefaultResult ? mapResult(action, action.getDefaultResult({ remotes })) : null
)
.filter((result): result is ResolvedToolbarResult => result !== null)
}
function mapResult(
action: ToolbarActionDefinition,
result: ToolbarActionResult
): ResolvedToolbarResult {
return {
id: serializeResult(action.id, result.args),
actionId: action.id,
label: result.label ?? action.label,
description: result.description ?? action.description,
args: result.args ?? {},
score: result.score ?? 0,
resolve: () => getToolbarAction(action.id),
}
}
function dedupeResults(results: ResolvedToolbarResult[]): ResolvedToolbarResult[] {
const bestById = new Map<string, ResolvedToolbarResult>()
for (const result of results) {
const key = `${result.actionId}:${JSON.stringify(result.args)}`
const existing = bestById.get(key)
if (!existing || result.score > existing.score) {
bestById.set(key, result)
}
}
return Array.from(bestById.values())
}
function serializeResult(actionId: ToolbarCommandId, args: ToolbarActionArgs) {
return `${actionId}:${JSON.stringify(args)}`
}
const WHITESPACE_SPLIT = /\s+/
const TOKEN_TRIM_REGEX = /^[\"'`]+|[\"'`.,;!?]+$/g
const REMOTE_PATH_REGEX = /^([^:\s]+):(.*)$/
const WINDOWS_DRIVE_REGEX = /^[a-zA-Z]:[\\/]/
const ALPHA_REGEX = /[a-zA-Z]/
const WINDOWS_PREFIX_REGEX = /^([a-zA-Z]:)(.*)$/
function extractPaths(
input: string,
remotes: string[],
remoteTypes?: Record<string, string>
): ToolbarActionPath[] {
const matches = input.split(WHITESPACE_SPLIT).filter(Boolean)
const seen = new Set<string>()
const results: ToolbarActionPath[] = []
const separator = sep()
console.log('remotes', remotes)
for (const raw of matches) {
const cleaned = stripToken(raw)
if (!cleaned) continue
let remoteName: string | undefined
let remoteType: string | undefined
let isLocal: boolean = false
// eagerly match remotes
if (remotes.includes(cleaned)) {
remoteName = cleaned
remoteType = remoteTypes?.[cleaned]
} else if (isRemotePath(cleaned)) {
// remote path match (e.g., "rct:/path/to/file")
const match = REMOTE_PATH_REGEX.exec(cleaned)
if (match && remotes.includes(match[1])) {
remoteName = match[1]
remoteType = remoteTypes?.[match[1]]
} else {
continue
}
} else if (isLocalPath(cleaned)) {
isLocal = true
} else {
continue
}
if (!seen.has(cleaned)) {
seen.add(cleaned)
results.push({
full: cleaned,
readable: createReadablePath(cleaned, isLocal, separator),
isLocal,
remoteName,
remoteType,
})
}
}
return results
}
function createReadablePath(full: string, isLocal: boolean, separator: string): string {
return isLocal ? createLocalReadable(full, separator) : createRemoteReadable(full)
}
function createRemoteReadable(full: string): string {
const match = REMOTE_PATH_REGEX.exec(full)
if (!match) {
return full
}
const remote = match[1]
let remainder = match[2] ?? ''
if (!remainder || remainder === '/') {
return `${remote}:/`
}
if (remainder.startsWith('/')) {
remainder = remainder.slice(1)
}
const segments = remainder.split('/').filter(Boolean)
if (segments.length === 0) {
return `${remote}:/`
}
const last = segments[segments.length - 1]
if (segments.length === 1) {
return `${remote}:/${last}`
}
if (segments.length === 2) {
return `${remote}:/${segments[0]}/${last}`
}
const secondToLast = segments[segments.length - 2]
return `${remote}:/${segments[0]}/.../${secondToLast}/${last}`
}
function createLocalReadable(full: string, separator: string): string {
const normalized = full.replace(/[/\\]+/g, separator)
const windowsMatch = WINDOWS_PREFIX_REGEX.exec(normalized)
if (windowsMatch) {
const drive = windowsMatch[1]
const remainder = windowsMatch[2] ?? ''
const segments = remainder.split(separator).filter(Boolean)
if (segments.length === 0) {
return `${drive}${separator}`
}
const last = segments.pop() ?? ''
if (segments.length === 0) {
return `${drive}${separator}${last}`
}
if (segments.length === 1) {
return `${drive}${separator}${segments[0]}${separator}${last}`
}
const secondToLast = segments.pop() ?? ''
const first = segments.shift() ?? ''
return `${drive}${separator}${first}${separator}...${separator}${secondToLast}${separator}${last}`
}
const isAbsolute =
normalized.startsWith(separator) ||
normalized.startsWith('/') ||
normalized.startsWith('\\')
const segments = normalized.split(separator).filter(Boolean)
if (segments.length === 0) {
return isAbsolute ? separator : normalized
}
const last = segments.pop() ?? ''
if (!isAbsolute && segments.length === 0) {
return last || normalized
}
const first = segments.shift()
if (!first) {
return isAbsolute ? `${separator}${last}` : last
}
if (segments.length === 0) {
return isAbsolute
? `${separator}${first}${separator}${last}`
: `${first}${separator}${last}`
}
if (segments.length === 1) {
return isAbsolute
? `${separator}${first}${separator}${segments[0]}${separator}${last}`
: `${first}${separator}${segments[0]}${separator}${last}`
}
const secondToLast = segments.pop() ?? ''
return isAbsolute
? `${separator}${first}${separator}...${separator}${secondToLast}${separator}${last}`
: `${first}${separator}...${separator}${secondToLast}${separator}${last}`
}
function stripToken(token: string): string {
return token.replace(TOKEN_TRIM_REGEX, '')
}
function isRemotePath(token: string): boolean {
if (!token.includes(':')) return false
if (token.includes('://')) return false
const match = REMOTE_PATH_REGEX.exec(token)
if (!match) return false
if (isWindowsDrive(match[1], match[2])) {
return false
}
return true
}
function isLocalPath(token: string): boolean {
if (token.startsWith('/')) return true
if (token.startsWith('~/')) return true
if (token.startsWith('./') || token.startsWith('../')) return true
if (WINDOWS_DRIVE_REGEX.test(token)) return true
return false
}
function isWindowsDrive(prefix: string, remainder: string): boolean {
return (
prefix.length === 1 &&
ALPHA_REGEX.test(prefix) &&
(remainder.startsWith('\\') || remainder.startsWith('/'))
)
}
+63
View File
@@ -0,0 +1,63 @@
export type ToolbarCommandId =
| 'copy'
| 'move'
| 'sync'
| 'mount'
| 'download'
| 'serve'
| 'bisync'
| 'delete'
| 'purge'
| 'cleanup'
| 'browse'
| 'settings'
| 'github'
| 'transfers'
| 'schedules'
| 'templates'
| 'remoteCreate'
| 'remoteEdit'
| 'remoteAutoMount'
| 'quit'
| 'remoteList'
export type ToolbarActionArgs = Record<string, any>
export interface ToolbarActionResult {
label: string
description?: string
args: ToolbarActionArgs
score?: number
}
export interface ToolbarActionOnPressContext {
openWindow: (options: { name: string; url: string }) => Promise<unknown>
}
export interface ToolbarActionPath {
full: string
readable: string
isLocal: boolean
remoteName?: string
remoteType?: string
}
export interface ToolbarActionContext {
query: string
fullQuery: string
paths: ToolbarActionPath[]
}
export interface ToolbarActionDefaultContext {
remotes: string[]
}
export interface ToolbarActionDefinition {
id: ToolbarCommandId
label: string
description?: string
keywords: string[]
getResults: (context: ToolbarActionContext) => ToolbarActionResult[]
getDefaultResult?: (context: ToolbarActionDefaultContext) => ToolbarActionResult
onPress: (args: ToolbarActionArgs, context: ToolbarActionOnPressContext) => Promise<void> | void
}
+32
View File
@@ -0,0 +1,32 @@
import type { fetchMountList, fetchServeList } from '../lib/rclone/api'
export function formatServeInfo(serve: Awaited<ReturnType<typeof fetchServeList>>[number]): string {
const parts = [`ID: ${serve.id}`, `Address: ${serve.addr}`]
if (serve.params?.opt?.password) {
parts.push(`Password: ${serve.params.opt.password}`)
}
if (serve.params?.type) {
parts.push(`Type: ${serve.params.type.toUpperCase()}`)
}
if (serve.params?.fs) {
parts.push(`Source: ${serve.params.fs}`)
}
return parts.join('\n')
}
export function formatServeLabel(
serve: Awaited<ReturnType<typeof fetchServeList>>[number]
): string {
const type = serve.params?.type?.toUpperCase() ?? 'SERVE'
const fs = serve.params?.fs ?? 'unknown'
return `${type} · ${fs} · ${serve.addr}`
}
export function formatMountLabel(
mount: Awaited<ReturnType<typeof fetchMountList>>[number]
): string {
return `MOUNT · ${mount.Fs} · ${mount.MountPoint}`
}