mirror of
https://github.com/OpenListTeam/OpenList-Desktop.git
synced 2025-11-25 03:14:56 +08:00
📦 Chore(custom): add prettier rules
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
// @ts-check
|
||||
import eslint from '@eslint/js'
|
||||
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
|
||||
import simpleImportSort from 'eslint-plugin-simple-import-sort'
|
||||
import eslintPluginUnicorn from 'eslint-plugin-unicorn'
|
||||
import pluginVue from 'eslint-plugin-vue'
|
||||
import globals from 'globals'
|
||||
import tseslint from 'typescript-eslint'
|
||||
|
||||
@@ -24,6 +25,8 @@ export default tseslint.config(
|
||||
eslint.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
...tseslint.configs.stylistic,
|
||||
...pluginVue.configs['flat/recommended'],
|
||||
eslintPluginPrettierRecommended,
|
||||
{
|
||||
plugins: {
|
||||
'simple-import-sort': simpleImportSort,
|
||||
@@ -39,7 +42,10 @@ export default tseslint.config(
|
||||
parserOptions: {
|
||||
warnOnUnsupportedTypeScriptVersion: false
|
||||
},
|
||||
globals: globals.node
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.browser
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -102,5 +108,19 @@ export default tseslint.config(
|
||||
{ name: 'exports' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['*.vue', '**/*.vue'],
|
||||
rules: {
|
||||
'no-undef': 'off'
|
||||
},
|
||||
languageOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
globals: globals.browser,
|
||||
parserOptions: {
|
||||
parser: tseslint.parser
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
23
package.json
23
package.json
@@ -26,8 +26,9 @@
|
||||
"tauri:dev": "cross-env RUST_BACKTRACE=1 tauri dev",
|
||||
"tauri": "tauri",
|
||||
"nowatch": "tauri dev --no-watch",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"lint:fix": "eslint src/**/*.ts --fix",
|
||||
"lint": "eslint --ext .js,.jsx,.ts,.tsx,.vue src/ scripts/",
|
||||
"lint:fix": "eslint --ext .js,.jsx,.ts,.tsx,.vue src/ scripts/ --fix",
|
||||
"lint:dpdm": "dpdm -T --tsconfig ./tsconfig.json --no-tree --no-warning --exit-code circular:1 src/main.ts",
|
||||
"i18n:check": "node scripts/find-unused-i18n.js",
|
||||
"i18n:check:verbose": "node scripts/find-unused-i18n.js --verbose",
|
||||
"cz": "git-cz",
|
||||
@@ -63,36 +64,42 @@
|
||||
"@tauri-apps/plugin-fs": "^2.4.2",
|
||||
"@tauri-apps/plugin-opener": "^2.5.0",
|
||||
"@tauri-apps/plugin-process": "^2.3.0",
|
||||
"@tauri-apps/plugin-shell": "^2.3.0",
|
||||
"@tauri-apps/plugin-shell": "^2.3.1",
|
||||
"@tauri-apps/plugin-store": "^2.4.0",
|
||||
"chrono-node": "^2.8.4",
|
||||
"lucide-vue-next": "^0.541.0",
|
||||
"lucide-vue-next": "^0.542.0",
|
||||
"pinia": "^3.0.3",
|
||||
"vue": "^3.5.19",
|
||||
"vue-i18n": "11.1.11",
|
||||
"vue-router": "^4.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^2.8.2",
|
||||
"@tauri-apps/cli": "^2.8.3",
|
||||
"@types/node": "^24.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.40.0",
|
||||
"@typescript-eslint/parser": "^8.40.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.41.0",
|
||||
"@typescript-eslint/parser": "^8.41.0",
|
||||
"@vitejs/plugin-vue": "^6.0.1",
|
||||
"adm-zip": "^0.5.16",
|
||||
"cross-env": "^7.0.3",
|
||||
"dpdm": "^3.14.0",
|
||||
"eslint": "^9.34.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.4",
|
||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||
"eslint-plugin-unicorn": "^60.0.0",
|
||||
"eslint-plugin-vue": "^10.4.0",
|
||||
"fs-extra": "^11.3.1",
|
||||
"https-proxy-agent": "^7.0.6",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^16.1.5",
|
||||
"node-bump-version": "^2.0.0",
|
||||
"node-fetch": "^3.3.2",
|
||||
"prettier": "^3.6.2",
|
||||
"tar": "^7.4.3",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.40.0",
|
||||
"typescript-eslint": "^8.41.0",
|
||||
"vite": "^7.1.3",
|
||||
"vue-eslint-parser": "^10.2.0",
|
||||
"vue-tsc": "^3.0.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,404 +1,404 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { readdirSync, readFileSync } from 'node:fs'
|
||||
import { basename, dirname, extname, join, relative } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = dirname(__filename)
|
||||
|
||||
const LOCALE_DIR = join(__dirname, '../src/i18n/locales')
|
||||
const SRC_DIR = join(__dirname, '../src')
|
||||
|
||||
console.log(`\n🔍 Analyzing i18n keys in ${LOCALE_DIR} and source files in ${SRC_DIR}\n`)
|
||||
|
||||
const colors = {
|
||||
reset: '\x1b[0m',
|
||||
bright: '\x1b[1m',
|
||||
red: '\x1b[31m',
|
||||
green: '\x1b[32m',
|
||||
yellow: '\x1b[33m',
|
||||
blue: '\x1b[34m',
|
||||
magenta: '\x1b[35m',
|
||||
cyan: '\x1b[36m'
|
||||
}
|
||||
|
||||
function colorize(text, color) {
|
||||
return `${colors[color]}${text}${colors.reset}`
|
||||
}
|
||||
|
||||
function flattenKeys(obj, prefix = '') {
|
||||
const keys = []
|
||||
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
const fullKey = prefix ? `${prefix}.${key}` : key
|
||||
|
||||
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
||||
keys.push(...flattenKeys(value, fullKey))
|
||||
} else {
|
||||
keys.push(fullKey)
|
||||
}
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
function readLocaleFile(filePath) {
|
||||
try {
|
||||
const content = readFileSync(filePath, 'utf8')
|
||||
return JSON.parse(content)
|
||||
} catch (error) {
|
||||
console.error(colorize(`Error reading ${filePath}: ${error.message}`, 'red'))
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function getAllI18nKeys() {
|
||||
const localeFiles = readdirSync(LOCALE_DIR).filter(file => file.endsWith('.json'))
|
||||
const allKeys = new Set()
|
||||
const localeData = {}
|
||||
|
||||
console.log(colorize('\n📁 Found locale files:', 'blue'))
|
||||
|
||||
for (const file of localeFiles) {
|
||||
const filePath = join(LOCALE_DIR, file)
|
||||
const locale = basename(file, '.json')
|
||||
const data = readLocaleFile(filePath)
|
||||
const keys = flattenKeys(data)
|
||||
|
||||
localeData[locale] = {
|
||||
file: filePath,
|
||||
keys,
|
||||
data
|
||||
}
|
||||
|
||||
keys.forEach(key => allKeys.add(key))
|
||||
|
||||
console.log(` ${colorize('✓', 'green')} ${file} (${keys.length} keys)`)
|
||||
}
|
||||
|
||||
return {
|
||||
allKeys: Array.from(allKeys).sort(),
|
||||
localeData
|
||||
}
|
||||
}
|
||||
|
||||
function findFiles(dir, extensions = ['.vue', '.ts', '.js']) {
|
||||
const files = []
|
||||
|
||||
function walk(currentDir) {
|
||||
const entries = readdirSync(currentDir, { withFileTypes: true })
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = join(currentDir, entry.name)
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
if (!['node_modules', '.git', 'dist', 'build', 'target'].includes(entry.name)) {
|
||||
walk(fullPath)
|
||||
}
|
||||
} else if (entry.isFile()) {
|
||||
const ext = extname(entry.name)
|
||||
if (extensions.includes(ext)) {
|
||||
files.push(fullPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
walk(dir)
|
||||
return files
|
||||
}
|
||||
|
||||
function findKeyUsage(keys) {
|
||||
const usage = {}
|
||||
const dynamicPatterns = []
|
||||
|
||||
keys.forEach(key => {
|
||||
usage[key] = {
|
||||
used: false,
|
||||
files: [],
|
||||
patterns: [],
|
||||
dynamicMatch: false
|
||||
}
|
||||
})
|
||||
|
||||
console.log(colorize('\n🔍 Searching for key usage in source files...', 'blue'))
|
||||
|
||||
const sourceFiles = findFiles(SRC_DIR)
|
||||
|
||||
console.log(` Found ${sourceFiles.length} source files to analyze`)
|
||||
|
||||
const searchPatterns = [
|
||||
/\$?t\s*\(\s*['"`]([^'"`]+)['"`]/g,
|
||||
/(?:^|[^a-zA-Z])t\s*\(\s*['"`]([^'"`]+)['"`]/g,
|
||||
/\{\{\s*\$?t\s*\(\s*['"`]([^'"`]+)['"`]/g
|
||||
]
|
||||
|
||||
const dynamicPattern = /\$?t\s*\(\s*`([^`]*\$\{[^}]+\}[^`]*)`/g
|
||||
|
||||
sourceFiles.forEach(filePath => {
|
||||
try {
|
||||
const content = readFileSync(filePath, 'utf8')
|
||||
const relativePath = relative(join(__dirname, '..'), filePath)
|
||||
|
||||
searchPatterns.forEach((pattern, patternIndex) => {
|
||||
let match
|
||||
while ((match = pattern.exec(content)) !== null) {
|
||||
const key = match[1]
|
||||
if (usage[key]) {
|
||||
usage[key].used = true
|
||||
if (!usage[key].files.includes(relativePath)) {
|
||||
usage[key].files.push(relativePath)
|
||||
}
|
||||
if (!usage[key].patterns.includes(patternIndex)) {
|
||||
usage[key].patterns.push(patternIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let dynamicMatch
|
||||
while ((dynamicMatch = dynamicPattern.exec(content)) !== null) {
|
||||
const templateString = dynamicMatch[1]
|
||||
|
||||
const staticParts = templateString.split(/\$\{[^}]+\}/)
|
||||
|
||||
const patternInfo = {
|
||||
template: templateString,
|
||||
file: relativePath,
|
||||
staticParts
|
||||
}
|
||||
|
||||
if (!dynamicPatterns.some(p => p.template === templateString && p.file === relativePath)) {
|
||||
dynamicPatterns.push(patternInfo)
|
||||
}
|
||||
|
||||
keys.forEach(key => {
|
||||
if (matchesDynamicPattern(key, staticParts)) {
|
||||
if (usage[key]) {
|
||||
usage[key].used = true
|
||||
usage[key].dynamicMatch = true
|
||||
if (!usage[key].files.includes(relativePath)) {
|
||||
usage[key].files.push(relativePath)
|
||||
}
|
||||
if (!usage[key].patterns.includes('dynamic')) {
|
||||
usage[key].patterns.push('dynamic')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(colorize(`Error reading ${filePath}: ${error.message}`, 'red'))
|
||||
}
|
||||
})
|
||||
|
||||
usage._dynamicPatterns = dynamicPatterns
|
||||
|
||||
return usage
|
||||
}
|
||||
|
||||
function matchesDynamicPattern(key, staticParts) {
|
||||
if (staticParts.length === 0) return false
|
||||
|
||||
let keyIndex = 0
|
||||
|
||||
for (let i = 0; i < staticParts.length; i++) {
|
||||
const part = staticParts[i]
|
||||
|
||||
if (part === '') {
|
||||
if (i < staticParts.length - 1) {
|
||||
const nextPart = staticParts[i + 1]
|
||||
if (nextPart) {
|
||||
const nextIndex = key.indexOf(nextPart, keyIndex)
|
||||
if (nextIndex === -1) return false
|
||||
keyIndex = nextIndex
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (i === 0) {
|
||||
if (!key.startsWith(part)) return false
|
||||
keyIndex = part.length
|
||||
} else if (i === staticParts.length - 1) {
|
||||
if (part && !key.endsWith(part)) return false
|
||||
} else {
|
||||
const index = key.indexOf(part, keyIndex)
|
||||
if (index === -1) return false
|
||||
keyIndex = index + part.length
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
function findLocaleInconsistencies(localeData) {
|
||||
const locales = Object.keys(localeData)
|
||||
const inconsistencies = {}
|
||||
|
||||
if (locales.length < 2) {
|
||||
return inconsistencies
|
||||
}
|
||||
|
||||
locales.forEach(locale => {
|
||||
const currentKeys = new Set(localeData[locale].keys)
|
||||
inconsistencies[locale] = {
|
||||
missing: [],
|
||||
extra: []
|
||||
}
|
||||
|
||||
locales.forEach(otherLocale => {
|
||||
if (locale !== otherLocale) {
|
||||
localeData[otherLocale].keys.forEach(key => {
|
||||
if (!currentKeys.has(key) && !inconsistencies[locale].missing.includes(key)) {
|
||||
inconsistencies[locale].missing.push(key)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
localeData[locale].keys.forEach(key => {
|
||||
const existsInOthers = locales.some(
|
||||
otherLocale => locale !== otherLocale && localeData[otherLocale].keys.includes(key)
|
||||
)
|
||||
if (!existsInOthers) {
|
||||
inconsistencies[locale].extra.push(key)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return inconsistencies
|
||||
}
|
||||
|
||||
function main() {
|
||||
console.log(colorize('🌐 OpenList Desktop - I18n Usage Analyzer', 'cyan'))
|
||||
console.log(colorize('==========================================', 'cyan'))
|
||||
|
||||
const { allKeys, localeData } = getAllI18nKeys()
|
||||
|
||||
console.log(colorize(`\n📊 Total unique keys found: ${allKeys.length}`, 'yellow'))
|
||||
const usage = findKeyUsage(allKeys)
|
||||
const dynamicPatterns = usage._dynamicPatterns || []
|
||||
delete usage._dynamicPatterns
|
||||
|
||||
const usedKeys = allKeys.filter(key => usage[key].used)
|
||||
const unusedKeys = allKeys.filter(key => !usage[key].used)
|
||||
const dynamicallyUsedKeys = usedKeys.filter(key => usage[key].dynamicMatch)
|
||||
const staticUsedKeys = usedKeys.filter(key => !usage[key].dynamicMatch)
|
||||
|
||||
const inconsistencies = findLocaleInconsistencies(localeData)
|
||||
|
||||
console.log(colorize('\n📈 Usage Summary:', 'blue'))
|
||||
console.log(` ${colorize('✓', 'green')} Used keys: ${usedKeys.length}`)
|
||||
console.log(` ${colorize('→', 'cyan')} Static usage: ${staticUsedKeys.length}`)
|
||||
console.log(` ${colorize('→', 'magenta')} Dynamic usage: ${dynamicallyUsedKeys.length}`)
|
||||
console.log(` ${colorize('✗', 'red')} Unused keys: ${unusedKeys.length}`)
|
||||
console.log(` ${colorize('📊', 'yellow')} Usage rate: ${((usedKeys.length / allKeys.length) * 100).toFixed(1)}%`)
|
||||
|
||||
if (dynamicPatterns.length > 0) {
|
||||
console.log(colorize('\n🔮 Dynamic I18n Patterns Detected:', 'magenta'))
|
||||
console.log(colorize('===================================', 'magenta'))
|
||||
|
||||
dynamicPatterns.forEach((pattern, index) => {
|
||||
console.log(colorize(`\n${index + 1}. Template: \`${pattern.template}\``, 'cyan'))
|
||||
console.log(` File: ${pattern.file}`)
|
||||
console.log(` Static parts: [${pattern.staticParts.map(p => `"${p}"`).join(', ')}]`)
|
||||
|
||||
const matchingKeys = allKeys.filter(key => matchesDynamicPattern(key, pattern.staticParts))
|
||||
if (matchingKeys.length > 0) {
|
||||
console.log(
|
||||
` ${colorize('Matches', 'green')} (${matchingKeys.length}): ${matchingKeys.slice(0, 5).join(', ')}${
|
||||
matchingKeys.length > 5 ? '...' : ''
|
||||
}`
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (unusedKeys.length > 0) {
|
||||
console.log(colorize('\n🗑️ Unused I18n Keys:', 'red'))
|
||||
console.log(colorize('====================', 'red'))
|
||||
|
||||
const groupedUnused = {}
|
||||
unusedKeys.forEach(key => {
|
||||
const namespace = key.split('.')[0]
|
||||
if (!groupedUnused[namespace]) {
|
||||
groupedUnused[namespace] = []
|
||||
}
|
||||
groupedUnused[namespace].push(key)
|
||||
})
|
||||
|
||||
Object.entries(groupedUnused).forEach(([namespace, keys]) => {
|
||||
console.log(colorize(`\n[${namespace}] - ${keys.length} unused keys:`, 'yellow'))
|
||||
keys.forEach(key => {
|
||||
console.log(` ${colorize('✗', 'red')} ${key}`)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
console.log(colorize('\n🎉 No unused keys found! All i18n keys are being used.', 'green'))
|
||||
}
|
||||
|
||||
const hasInconsistencies = Object.values(inconsistencies).some(inc => inc.missing.length > 0 || inc.extra.length > 0)
|
||||
|
||||
if (hasInconsistencies) {
|
||||
console.log(colorize('\n⚠️ Locale Inconsistencies:', 'yellow'))
|
||||
console.log(colorize('=========================', 'yellow'))
|
||||
|
||||
Object.entries(inconsistencies).forEach(([locale, data]) => {
|
||||
if (data.missing.length > 0 || data.extra.length > 0) {
|
||||
console.log(colorize(`\n[${locale}.json]:`, 'cyan'))
|
||||
|
||||
if (data.missing.length > 0) {
|
||||
console.log(colorize(` Missing ${data.missing.length} keys:`, 'red'))
|
||||
data.missing.forEach(key => {
|
||||
console.log(` ${colorize('✗', 'red')} ${key}`)
|
||||
})
|
||||
}
|
||||
|
||||
if (data.extra.length > 0) {
|
||||
console.log(colorize(` Extra ${data.extra.length} keys:`, 'blue'))
|
||||
data.extra.forEach(key => {
|
||||
console.log(` ${colorize('!', 'blue')} ${key}`)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (process.argv.includes('--verbose') || process.argv.includes('-v')) {
|
||||
console.log(colorize('\n📋 Sample Used Keys (first 10):', 'blue'))
|
||||
console.log(colorize('=================================', 'blue'))
|
||||
|
||||
usedKeys.slice(0, 10).forEach(key => {
|
||||
const files = usage[key].files.slice(0, 3) // Show first 3 files
|
||||
const moreFiles = usage[key].files.length > 3 ? ` (+${usage[key].files.length - 3} more)` : ''
|
||||
const usageType = usage[key].dynamicMatch ? colorize('(dynamic)', 'magenta') : colorize('(static)', 'cyan')
|
||||
console.log(` ${colorize('✓', 'green')} ${key} ${usageType}`)
|
||||
console.log(` Used in: ${files.join(', ')}${moreFiles}`)
|
||||
})
|
||||
|
||||
if (dynamicallyUsedKeys.length > 0) {
|
||||
console.log(colorize('\n🔮 Dynamic Key Usage Details:', 'magenta'))
|
||||
console.log(colorize('=============================', 'magenta'))
|
||||
|
||||
dynamicallyUsedKeys.slice(0, 5).forEach(key => {
|
||||
const files = usage[key].files.slice(0, 2)
|
||||
console.log(` ${colorize('✨', 'magenta')} ${key}`)
|
||||
console.log(` Files: ${files.join(', ')}`)
|
||||
})
|
||||
|
||||
if (dynamicallyUsedKeys.length > 5) {
|
||||
console.log(` ... and ${dynamicallyUsedKeys.length - 5} more dynamic keys`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(colorize('\n✨ Analysis complete!', 'cyan'))
|
||||
|
||||
if (unusedKeys.length > 0) {
|
||||
console.log(colorize('\n💡 Tip: Run with --verbose (-v) flag to see usage details of used keys', 'blue'))
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { readdirSync, readFileSync } from 'node:fs'
|
||||
import { basename, dirname, extname, join, relative } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = dirname(__filename)
|
||||
|
||||
const LOCALE_DIR = join(__dirname, '../src/i18n/locales')
|
||||
const SRC_DIR = join(__dirname, '../src')
|
||||
|
||||
console.log(`\n🔍 Analyzing i18n keys in ${LOCALE_DIR} and source files in ${SRC_DIR}\n`)
|
||||
|
||||
const colors = {
|
||||
reset: '\x1b[0m',
|
||||
bright: '\x1b[1m',
|
||||
red: '\x1b[31m',
|
||||
green: '\x1b[32m',
|
||||
yellow: '\x1b[33m',
|
||||
blue: '\x1b[34m',
|
||||
magenta: '\x1b[35m',
|
||||
cyan: '\x1b[36m'
|
||||
}
|
||||
|
||||
function colorize(text, color) {
|
||||
return `${colors[color]}${text}${colors.reset}`
|
||||
}
|
||||
|
||||
function flattenKeys(obj, prefix = '') {
|
||||
const keys = []
|
||||
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
const fullKey = prefix ? `${prefix}.${key}` : key
|
||||
|
||||
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
||||
keys.push(...flattenKeys(value, fullKey))
|
||||
} else {
|
||||
keys.push(fullKey)
|
||||
}
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
function readLocaleFile(filePath) {
|
||||
try {
|
||||
const content = readFileSync(filePath, 'utf8')
|
||||
return JSON.parse(content)
|
||||
} catch (error) {
|
||||
console.error(colorize(`Error reading ${filePath}: ${error.message}`, 'red'))
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function getAllI18nKeys() {
|
||||
const localeFiles = readdirSync(LOCALE_DIR).filter(file => file.endsWith('.json'))
|
||||
const allKeys = new Set()
|
||||
const localeData = {}
|
||||
|
||||
console.log(colorize('\n📁 Found locale files:', 'blue'))
|
||||
|
||||
for (const file of localeFiles) {
|
||||
const filePath = join(LOCALE_DIR, file)
|
||||
const locale = basename(file, '.json')
|
||||
const data = readLocaleFile(filePath)
|
||||
const keys = flattenKeys(data)
|
||||
|
||||
localeData[locale] = {
|
||||
file: filePath,
|
||||
keys,
|
||||
data
|
||||
}
|
||||
|
||||
keys.forEach(key => allKeys.add(key))
|
||||
|
||||
console.log(` ${colorize('✓', 'green')} ${file} (${keys.length} keys)`)
|
||||
}
|
||||
|
||||
return {
|
||||
allKeys: Array.from(allKeys).sort(),
|
||||
localeData
|
||||
}
|
||||
}
|
||||
|
||||
function findFiles(dir, extensions = ['.vue', '.ts', '.js']) {
|
||||
const files = []
|
||||
|
||||
function walk(currentDir) {
|
||||
const entries = readdirSync(currentDir, { withFileTypes: true })
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = join(currentDir, entry.name)
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
if (!['node_modules', '.git', 'dist', 'build', 'target'].includes(entry.name)) {
|
||||
walk(fullPath)
|
||||
}
|
||||
} else if (entry.isFile()) {
|
||||
const ext = extname(entry.name)
|
||||
if (extensions.includes(ext)) {
|
||||
files.push(fullPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
walk(dir)
|
||||
return files
|
||||
}
|
||||
|
||||
function findKeyUsage(keys) {
|
||||
const usage = {}
|
||||
const dynamicPatterns = []
|
||||
|
||||
keys.forEach(key => {
|
||||
usage[key] = {
|
||||
used: false,
|
||||
files: [],
|
||||
patterns: [],
|
||||
dynamicMatch: false
|
||||
}
|
||||
})
|
||||
|
||||
console.log(colorize('\n🔍 Searching for key usage in source files...', 'blue'))
|
||||
|
||||
const sourceFiles = findFiles(SRC_DIR)
|
||||
|
||||
console.log(` Found ${sourceFiles.length} source files to analyze`)
|
||||
|
||||
const searchPatterns = [
|
||||
/\$?t\s*\(\s*['"`]([^'"`]+)['"`]/g,
|
||||
/(?:^|[^a-zA-Z])t\s*\(\s*['"`]([^'"`]+)['"`]/g,
|
||||
/\{\{\s*\$?t\s*\(\s*['"`]([^'"`]+)['"`]/g
|
||||
]
|
||||
|
||||
const dynamicPattern = /\$?t\s*\(\s*`([^`]*\$\{[^}]+\}[^`]*)`/g
|
||||
|
||||
sourceFiles.forEach(filePath => {
|
||||
try {
|
||||
const content = readFileSync(filePath, 'utf8')
|
||||
const relativePath = relative(join(__dirname, '..'), filePath)
|
||||
|
||||
searchPatterns.forEach((pattern, patternIndex) => {
|
||||
let match
|
||||
while ((match = pattern.exec(content)) !== null) {
|
||||
const key = match[1]
|
||||
if (usage[key]) {
|
||||
usage[key].used = true
|
||||
if (!usage[key].files.includes(relativePath)) {
|
||||
usage[key].files.push(relativePath)
|
||||
}
|
||||
if (!usage[key].patterns.includes(patternIndex)) {
|
||||
usage[key].patterns.push(patternIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let dynamicMatch
|
||||
while ((dynamicMatch = dynamicPattern.exec(content)) !== null) {
|
||||
const templateString = dynamicMatch[1]
|
||||
|
||||
const staticParts = templateString.split(/\$\{[^}]+\}/)
|
||||
|
||||
const patternInfo = {
|
||||
template: templateString,
|
||||
file: relativePath,
|
||||
staticParts
|
||||
}
|
||||
|
||||
if (!dynamicPatterns.some(p => p.template === templateString && p.file === relativePath)) {
|
||||
dynamicPatterns.push(patternInfo)
|
||||
}
|
||||
|
||||
keys.forEach(key => {
|
||||
if (matchesDynamicPattern(key, staticParts)) {
|
||||
if (usage[key]) {
|
||||
usage[key].used = true
|
||||
usage[key].dynamicMatch = true
|
||||
if (!usage[key].files.includes(relativePath)) {
|
||||
usage[key].files.push(relativePath)
|
||||
}
|
||||
if (!usage[key].patterns.includes('dynamic')) {
|
||||
usage[key].patterns.push('dynamic')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(colorize(`Error reading ${filePath}: ${error.message}`, 'red'))
|
||||
}
|
||||
})
|
||||
|
||||
usage._dynamicPatterns = dynamicPatterns
|
||||
|
||||
return usage
|
||||
}
|
||||
|
||||
function matchesDynamicPattern(key, staticParts) {
|
||||
if (staticParts.length === 0) return false
|
||||
|
||||
let keyIndex = 0
|
||||
|
||||
for (let i = 0; i < staticParts.length; i++) {
|
||||
const part = staticParts[i]
|
||||
|
||||
if (part === '') {
|
||||
if (i < staticParts.length - 1) {
|
||||
const nextPart = staticParts[i + 1]
|
||||
if (nextPart) {
|
||||
const nextIndex = key.indexOf(nextPart, keyIndex)
|
||||
if (nextIndex === -1) return false
|
||||
keyIndex = nextIndex
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (i === 0) {
|
||||
if (!key.startsWith(part)) return false
|
||||
keyIndex = part.length
|
||||
} else if (i === staticParts.length - 1) {
|
||||
if (part && !key.endsWith(part)) return false
|
||||
} else {
|
||||
const index = key.indexOf(part, keyIndex)
|
||||
if (index === -1) return false
|
||||
keyIndex = index + part.length
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
function findLocaleInconsistencies(localeData) {
|
||||
const locales = Object.keys(localeData)
|
||||
const inconsistencies = {}
|
||||
|
||||
if (locales.length < 2) {
|
||||
return inconsistencies
|
||||
}
|
||||
|
||||
locales.forEach(locale => {
|
||||
const currentKeys = new Set(localeData[locale].keys)
|
||||
inconsistencies[locale] = {
|
||||
missing: [],
|
||||
extra: []
|
||||
}
|
||||
|
||||
locales.forEach(otherLocale => {
|
||||
if (locale !== otherLocale) {
|
||||
localeData[otherLocale].keys.forEach(key => {
|
||||
if (!currentKeys.has(key) && !inconsistencies[locale].missing.includes(key)) {
|
||||
inconsistencies[locale].missing.push(key)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
localeData[locale].keys.forEach(key => {
|
||||
const existsInOthers = locales.some(
|
||||
otherLocale => locale !== otherLocale && localeData[otherLocale].keys.includes(key)
|
||||
)
|
||||
if (!existsInOthers) {
|
||||
inconsistencies[locale].extra.push(key)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return inconsistencies
|
||||
}
|
||||
|
||||
function main() {
|
||||
console.log(colorize('🌐 OpenList Desktop - I18n Usage Analyzer', 'cyan'))
|
||||
console.log(colorize('==========================================', 'cyan'))
|
||||
|
||||
const { allKeys, localeData } = getAllI18nKeys()
|
||||
|
||||
console.log(colorize(`\n📊 Total unique keys found: ${allKeys.length}`, 'yellow'))
|
||||
const usage = findKeyUsage(allKeys)
|
||||
const dynamicPatterns = usage._dynamicPatterns || []
|
||||
delete usage._dynamicPatterns
|
||||
|
||||
const usedKeys = allKeys.filter(key => usage[key].used)
|
||||
const unusedKeys = allKeys.filter(key => !usage[key].used)
|
||||
const dynamicallyUsedKeys = usedKeys.filter(key => usage[key].dynamicMatch)
|
||||
const staticUsedKeys = usedKeys.filter(key => !usage[key].dynamicMatch)
|
||||
|
||||
const inconsistencies = findLocaleInconsistencies(localeData)
|
||||
|
||||
console.log(colorize('\n📈 Usage Summary:', 'blue'))
|
||||
console.log(` ${colorize('✓', 'green')} Used keys: ${usedKeys.length}`)
|
||||
console.log(` ${colorize('→', 'cyan')} Static usage: ${staticUsedKeys.length}`)
|
||||
console.log(` ${colorize('→', 'magenta')} Dynamic usage: ${dynamicallyUsedKeys.length}`)
|
||||
console.log(` ${colorize('✗', 'red')} Unused keys: ${unusedKeys.length}`)
|
||||
console.log(` ${colorize('📊', 'yellow')} Usage rate: ${((usedKeys.length / allKeys.length) * 100).toFixed(1)}%`)
|
||||
|
||||
if (dynamicPatterns.length > 0) {
|
||||
console.log(colorize('\n🔮 Dynamic I18n Patterns Detected:', 'magenta'))
|
||||
console.log(colorize('===================================', 'magenta'))
|
||||
|
||||
dynamicPatterns.forEach((pattern, index) => {
|
||||
console.log(colorize(`\n${index + 1}. Template: \`${pattern.template}\``, 'cyan'))
|
||||
console.log(` File: ${pattern.file}`)
|
||||
console.log(` Static parts: [${pattern.staticParts.map(p => `"${p}"`).join(', ')}]`)
|
||||
|
||||
const matchingKeys = allKeys.filter(key => matchesDynamicPattern(key, pattern.staticParts))
|
||||
if (matchingKeys.length > 0) {
|
||||
console.log(
|
||||
` ${colorize('Matches', 'green')} (${matchingKeys.length}): ${matchingKeys.slice(0, 5).join(', ')}${
|
||||
matchingKeys.length > 5 ? '...' : ''
|
||||
}`
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (unusedKeys.length > 0) {
|
||||
console.log(colorize('\n🗑️ Unused I18n Keys:', 'red'))
|
||||
console.log(colorize('====================', 'red'))
|
||||
|
||||
const groupedUnused = {}
|
||||
unusedKeys.forEach(key => {
|
||||
const namespace = key.split('.')[0]
|
||||
if (!groupedUnused[namespace]) {
|
||||
groupedUnused[namespace] = []
|
||||
}
|
||||
groupedUnused[namespace].push(key)
|
||||
})
|
||||
|
||||
Object.entries(groupedUnused).forEach(([namespace, keys]) => {
|
||||
console.log(colorize(`\n[${namespace}] - ${keys.length} unused keys:`, 'yellow'))
|
||||
keys.forEach(key => {
|
||||
console.log(` ${colorize('✗', 'red')} ${key}`)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
console.log(colorize('\n🎉 No unused keys found! All i18n keys are being used.', 'green'))
|
||||
}
|
||||
|
||||
const hasInconsistencies = Object.values(inconsistencies).some(inc => inc.missing.length > 0 || inc.extra.length > 0)
|
||||
|
||||
if (hasInconsistencies) {
|
||||
console.log(colorize('\n⚠️ Locale Inconsistencies:', 'yellow'))
|
||||
console.log(colorize('=========================', 'yellow'))
|
||||
|
||||
Object.entries(inconsistencies).forEach(([locale, data]) => {
|
||||
if (data.missing.length > 0 || data.extra.length > 0) {
|
||||
console.log(colorize(`\n[${locale}.json]:`, 'cyan'))
|
||||
|
||||
if (data.missing.length > 0) {
|
||||
console.log(colorize(` Missing ${data.missing.length} keys:`, 'red'))
|
||||
data.missing.forEach(key => {
|
||||
console.log(` ${colorize('✗', 'red')} ${key}`)
|
||||
})
|
||||
}
|
||||
|
||||
if (data.extra.length > 0) {
|
||||
console.log(colorize(` Extra ${data.extra.length} keys:`, 'blue'))
|
||||
data.extra.forEach(key => {
|
||||
console.log(` ${colorize('!', 'blue')} ${key}`)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (process.argv.includes('--verbose') || process.argv.includes('-v')) {
|
||||
console.log(colorize('\n📋 Sample Used Keys (first 10):', 'blue'))
|
||||
console.log(colorize('=================================', 'blue'))
|
||||
|
||||
usedKeys.slice(0, 10).forEach(key => {
|
||||
const files = usage[key].files.slice(0, 3) // Show first 3 files
|
||||
const moreFiles = usage[key].files.length > 3 ? ` (+${usage[key].files.length - 3} more)` : ''
|
||||
const usageType = usage[key].dynamicMatch ? colorize('(dynamic)', 'magenta') : colorize('(static)', 'cyan')
|
||||
console.log(` ${colorize('✓', 'green')} ${key} ${usageType}`)
|
||||
console.log(` Used in: ${files.join(', ')}${moreFiles}`)
|
||||
})
|
||||
|
||||
if (dynamicallyUsedKeys.length > 0) {
|
||||
console.log(colorize('\n🔮 Dynamic Key Usage Details:', 'magenta'))
|
||||
console.log(colorize('=============================', 'magenta'))
|
||||
|
||||
dynamicallyUsedKeys.slice(0, 5).forEach(key => {
|
||||
const files = usage[key].files.slice(0, 2)
|
||||
console.log(` ${colorize('✨', 'magenta')} ${key}`)
|
||||
console.log(` Files: ${files.join(', ')}`)
|
||||
})
|
||||
|
||||
if (dynamicallyUsedKeys.length > 5) {
|
||||
console.log(` ... and ${dynamicallyUsedKeys.length - 5} more dynamic keys`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(colorize('\n✨ Analysis complete!', 'cyan'))
|
||||
|
||||
if (unusedKeys.length > 0) {
|
||||
console.log(colorize('\n💡 Tip: Run with --verbose (-v) flag to see usage details of used keys', 'blue'))
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
11
src/App.vue
11
src/App.vue
@@ -2,12 +2,12 @@
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import { useAppStore } from './stores/app'
|
||||
import { TauriAPI } from './api/tauri'
|
||||
import Navigation from './components/NavigationPage.vue'
|
||||
import TitleBar from './components/ui/TitleBar.vue'
|
||||
import { useTranslation } from './composables/useI18n'
|
||||
import { useTray } from './composables/useTray'
|
||||
import { TauriAPI } from './api/tauri'
|
||||
import Navigation from './components/Navigation.vue'
|
||||
import TitleBar from './components/ui/TitleBar.vue'
|
||||
import { useAppStore } from './stores/app'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const { t } = useTranslation()
|
||||
@@ -365,7 +365,8 @@ body {
|
||||
.loading-backdrop {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: radial-gradient(circle at 25% 25%, rgba(120, 119, 198, 0.3) 0%, transparent 50%),
|
||||
background:
|
||||
radial-gradient(circle at 25% 25%, rgba(120, 119, 198, 0.3) 0%, transparent 50%),
|
||||
radial-gradient(circle at 75% 75%, rgba(255, 255, 255, 0.1) 0%, transparent 50%);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,49 +1,3 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useTranslation } from '../composables/useI18n'
|
||||
import { useAppStore } from '../stores/app'
|
||||
import LanguageSwitcher from './ui/LanguageSwitcher.vue'
|
||||
import ThemeSwitcher from './ui/ThemeSwitcher.vue'
|
||||
|
||||
import { Home, HardDrive, FileText, Settings, Download, DownloadCloud, Github } from 'lucide-vue-next'
|
||||
import { TauriAPI } from '@/api/tauri'
|
||||
|
||||
const { t } = useTranslation()
|
||||
const appStore = useAppStore()
|
||||
|
||||
const navigationItems = computed(() => [
|
||||
{ name: t('navigation.dashboard'), path: '/', icon: Home, shortcut: 'Ctrl+H' },
|
||||
{ name: t('navigation.mount'), path: '/mount', icon: HardDrive, shortcut: 'Ctrl+M' },
|
||||
{ name: t('navigation.logs'), path: '/logs', icon: FileText, shortcut: 'Ctrl+L' },
|
||||
{ name: t('navigation.settings'), path: '/settings', icon: Settings, shortcut: 'Ctrl+,' },
|
||||
{
|
||||
name: t('navigation.update'),
|
||||
path: '/update',
|
||||
icon: appStore.updateAvailable ? DownloadCloud : Download,
|
||||
shortcut: 'Ctrl+U',
|
||||
hasNotification: appStore.updateAvailable
|
||||
}
|
||||
])
|
||||
|
||||
const isMacOs = computed(() => {
|
||||
return typeof OS_PLATFORM !== 'undefined' && OS_PLATFORM === 'darwin'
|
||||
})
|
||||
|
||||
const openLink = async (url: string) => {
|
||||
try {
|
||||
if (appStore.settings.app.open_links_in_browser || isMacOs.value) {
|
||||
await TauriAPI.files.urlInBrowser(url)
|
||||
return
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to open link:', error)
|
||||
}
|
||||
setTimeout(() => {
|
||||
window.open(url, '_blank')
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="navigation">
|
||||
<div class="title-bar">
|
||||
@@ -82,9 +36,9 @@ const openLink = async (url: string) => {
|
||||
|
||||
<div class="github-section">
|
||||
<a
|
||||
@click.prevent="openLink('https://github.com/OpenListTeam/openlist-desktop')"
|
||||
class="github-link"
|
||||
title="View on GitHub"
|
||||
@click.prevent="openLink('https://github.com/OpenListTeam/openlist-desktop')"
|
||||
>
|
||||
<Github :size="20" />
|
||||
</a>
|
||||
@@ -92,6 +46,53 @@ const openLink = async (url: string) => {
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Download, DownloadCloud, FileText, Github, HardDrive, Home, Settings } from 'lucide-vue-next'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { TauriAPI } from '@/api/tauri'
|
||||
|
||||
import { useTranslation } from '../composables/useI18n'
|
||||
import { useAppStore } from '../stores/app'
|
||||
import LanguageSwitcher from './ui/LanguageSwitcher.vue'
|
||||
import ThemeSwitcher from './ui/ThemeSwitcher.vue'
|
||||
|
||||
const { t } = useTranslation()
|
||||
const appStore = useAppStore()
|
||||
|
||||
const navigationItems = computed(() => [
|
||||
{ name: t('navigation.dashboard'), path: '/', icon: Home, shortcut: 'Ctrl+H' },
|
||||
{ name: t('navigation.mount'), path: '/mount', icon: HardDrive, shortcut: 'Ctrl+M' },
|
||||
{ name: t('navigation.logs'), path: '/logs', icon: FileText, shortcut: 'Ctrl+L' },
|
||||
{ name: t('navigation.settings'), path: '/settings', icon: Settings, shortcut: 'Ctrl+,' },
|
||||
{
|
||||
name: t('navigation.update'),
|
||||
path: '/update',
|
||||
icon: appStore.updateAvailable ? DownloadCloud : Download,
|
||||
shortcut: 'Ctrl+U',
|
||||
hasNotification: appStore.updateAvailable
|
||||
}
|
||||
])
|
||||
|
||||
const isMacOs = computed(() => {
|
||||
return typeof OS_PLATFORM !== 'undefined' && OS_PLATFORM === 'darwin'
|
||||
})
|
||||
|
||||
const openLink = async (url: string) => {
|
||||
try {
|
||||
if (appStore.settings.app.open_links_in_browser || isMacOs.value) {
|
||||
await TauriAPI.files.urlInBrowser(url)
|
||||
return
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to open link:', error)
|
||||
}
|
||||
setTimeout(() => {
|
||||
window.open(url, '_blank')
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.navigation {
|
||||
display: flex;
|
||||
@@ -10,7 +10,7 @@
|
||||
<div class="heartbeat-section">
|
||||
<div class="heartbeat-header">
|
||||
<h4></h4>
|
||||
<div class="metrics" v-if="isCoreRunning">
|
||||
<div v-if="isCoreRunning" class="metrics">
|
||||
<span class="metric info">
|
||||
<Globe :size="14" />
|
||||
Port: {{ openlistCoreStatus.port || 5244 }}
|
||||
@@ -33,7 +33,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="heartbeat-chart" ref="chartContainer">
|
||||
<div ref="chartContainer" class="heartbeat-chart">
|
||||
<svg :width="chartWidth" :height="chartHeight" class="heartbeat-svg">
|
||||
<defs>
|
||||
<pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse">
|
||||
@@ -70,11 +70,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue'
|
||||
import { useAppStore } from '../../stores/app'
|
||||
import { Activity, Globe } from 'lucide-vue-next'
|
||||
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
|
||||
import { useTranslation } from '../../composables/useI18n'
|
||||
import Card from '../ui/Card.vue'
|
||||
import { Globe, Activity } from 'lucide-vue-next'
|
||||
import { useAppStore } from '../../stores/app'
|
||||
import Card from '../ui/CardPage.vue'
|
||||
|
||||
const { t } = useTranslation()
|
||||
const appStore = useAppStore()
|
||||
@@ -82,7 +83,7 @@ const appStore = useAppStore()
|
||||
const chartContainer = ref<HTMLElement>()
|
||||
const chartWidth = ref(400)
|
||||
const chartHeight = ref(120)
|
||||
const dataPoints = ref<Array<{ timestamp: number; responseTime: number; isHealthy: boolean }>>([])
|
||||
const dataPoints = ref<{ timestamp: number; responseTime: number; isHealthy: boolean }[]>([])
|
||||
const responseTime = ref(0)
|
||||
const startTime = ref(Date.now())
|
||||
const monitoringInterval = ref<number>()
|
||||
@@ -258,7 +259,9 @@ watch(isCoreRunning, (newValue: boolean, oldValue: boolean) => {
|
||||
border-radius: 20px;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border: 1px solid rgba(226, 232, 240, 0.6);
|
||||
transition: background-color 0.15s ease, border-color 0.15s ease;
|
||||
transition:
|
||||
background-color 0.15s ease,
|
||||
border-color 0.15s ease;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="doc-actions">
|
||||
<button @click="openOpenListDocs" class="doc-btn primary">
|
||||
<button class="doc-btn primary" @click="openOpenListDocs">
|
||||
<ExternalLink :size="14" />
|
||||
<span>{{ t('dashboard.documentation.openDocs') }}</span>
|
||||
</button>
|
||||
<button @click="openOpenListGitHub" class="doc-btn secondary">
|
||||
<button class="doc-btn secondary" @click="openOpenListGitHub">
|
||||
<Github :size="14" />
|
||||
<span>{{ t('dashboard.documentation.github') }}</span>
|
||||
</button>
|
||||
@@ -35,11 +35,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="doc-actions">
|
||||
<button @click="openRcloneDocs" class="doc-btn primary">
|
||||
<button class="doc-btn primary" @click="openRcloneDocs">
|
||||
<ExternalLink :size="14" />
|
||||
<span>{{ t('dashboard.documentation.openDocs') }}</span>
|
||||
</button>
|
||||
<button @click="openRcloneGitHub" class="doc-btn secondary">
|
||||
<button class="doc-btn secondary" @click="openRcloneGitHub">
|
||||
<Github :size="14" />
|
||||
<span>{{ t('dashboard.documentation.github') }}</span>
|
||||
</button>
|
||||
@@ -52,19 +52,19 @@
|
||||
<h4>{{ t('dashboard.documentation.quickLinks') }}</h4>
|
||||
</div>
|
||||
<div class="links-grid">
|
||||
<button @click="openLink('https://docs.oplist.org/guide/api')" class="link-btn">
|
||||
<button class="link-btn" @click="openLink('https://docs.oplist.org/guide/api')">
|
||||
<Code :size="16" />
|
||||
<span>{{ t('dashboard.documentation.apiDocs') }}</span>
|
||||
</button>
|
||||
<button @click="openLink('https://rclone.org/commands/')" class="link-btn">
|
||||
<button class="link-btn" @click="openLink('https://rclone.org/commands/')">
|
||||
<Terminal :size="16" />
|
||||
<span>{{ t('dashboard.documentation.commands') }}</span>
|
||||
</button>
|
||||
<button @click="openLink('https://github.com/OpenListTeam/OpenList-desktop/issues')" class="link-btn">
|
||||
<button class="link-btn" @click="openLink('https://github.com/OpenListTeam/OpenList-desktop/issues')">
|
||||
<HelpCircle :size="16" />
|
||||
<span>{{ t('dashboard.documentation.issues') }}</span>
|
||||
</button>
|
||||
<button @click="openLink('https://docs.oplist.org/faq/')" class="link-btn">
|
||||
<button class="link-btn" @click="openLink('https://docs.oplist.org/faq/')">
|
||||
<MessageCircle :size="16" />
|
||||
<span>{{ t('dashboard.documentation.faq') }}</span>
|
||||
</button>
|
||||
@@ -75,13 +75,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useTranslation } from '../../composables/useI18n'
|
||||
import { ExternalLink, Github, BookOpen, Cloud, Code, Terminal, HelpCircle, MessageCircle } from 'lucide-vue-next'
|
||||
import Card from '../ui/Card.vue'
|
||||
import { TauriAPI } from '../../api/tauri'
|
||||
import { useAppStore } from '../../stores/app'
|
||||
import { BookOpen, Cloud, Code, ExternalLink, Github, HelpCircle, MessageCircle, Terminal } from 'lucide-vue-next'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { TauriAPI } from '../../api/tauri'
|
||||
import { useTranslation } from '../../composables/useI18n'
|
||||
import { useAppStore } from '../../stores/app'
|
||||
import Card from '../ui/CardPage.vue'
|
||||
|
||||
const { t } = useTranslation()
|
||||
const appStore = useAppStore()
|
||||
|
||||
|
||||
@@ -10,19 +10,19 @@
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
@click="toggleCore"
|
||||
:disabled="isCoreLoading"
|
||||
:class="['action-btn', 'service-btn', { running: isCoreRunning, loading: isCoreLoading }]"
|
||||
@click="toggleCore"
|
||||
>
|
||||
<component v-if="!isCoreLoading" :is="serviceButtonIcon" :size="20" />
|
||||
<component :is="serviceButtonIcon" v-if="!isCoreLoading" :size="20" />
|
||||
<Loader v-else :size="20" class="loading-icon" />
|
||||
<span>{{ isCoreLoading ? t('dashboard.quickActions.processing') : serviceButtonText }}</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="restartCore"
|
||||
:disabled="!isCoreRunning || isCoreLoading"
|
||||
:class="['action-btn', 'restart-btn', { loading: isCoreLoading }]"
|
||||
@click="restartCore"
|
||||
>
|
||||
<RotateCcw v-if="!isCoreLoading" :size="18" />
|
||||
<Loader v-else :size="18" class="loading-icon" />
|
||||
@@ -30,27 +30,27 @@
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="openWebUI"
|
||||
:disabled="!isCoreRunning || isCoreLoading"
|
||||
class="action-btn web-btn"
|
||||
:title="appStore.openListCoreUrl"
|
||||
@click="openWebUI"
|
||||
>
|
||||
<ExternalLink :size="18" />
|
||||
<span>{{ t('dashboard.quickActions.openWeb') }}</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="copyAdminPassword"
|
||||
class="action-btn password-btn icon-only-btn"
|
||||
:title="t('dashboard.quickActions.copyAdminPassword')"
|
||||
@click="copyAdminPassword"
|
||||
>
|
||||
<Key :size="16" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="resetAdminPassword"
|
||||
class="action-btn reset-password-btn icon-only-btn"
|
||||
:title="t('dashboard.quickActions.resetAdminPassword')"
|
||||
@click="resetAdminPassword"
|
||||
>
|
||||
<RotateCcw :size="16" />
|
||||
</button>
|
||||
@@ -66,31 +66,31 @@
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
@click="rcloneStore.serviceRunning ? stopBackend() : startBackend()"
|
||||
:disabled="isRcloneLoading"
|
||||
:class="[
|
||||
'action-btn',
|
||||
'service-indicator-btn',
|
||||
{ active: rcloneStore.serviceRunning, loading: isRcloneLoading }
|
||||
]"
|
||||
@click="rcloneStore.serviceRunning ? stopBackend() : startBackend()"
|
||||
>
|
||||
<component v-if="!isRcloneLoading" :is="rcloneStore.serviceRunning ? Square : Play" :size="18" />
|
||||
<component :is="rcloneStore.serviceRunning ? Square : Play" v-if="!isRcloneLoading" :size="18" />
|
||||
<Loader v-else :size="18" class="loading-icon" />
|
||||
<span>{{
|
||||
isRcloneLoading
|
||||
? t('dashboard.quickActions.processing')
|
||||
: rcloneStore.serviceRunning
|
||||
? t('dashboard.quickActions.stopRclone')
|
||||
: t('dashboard.quickActions.startRclone')
|
||||
? t('dashboard.quickActions.stopRclone')
|
||||
: t('dashboard.quickActions.startRclone')
|
||||
}}</span>
|
||||
</button>
|
||||
|
||||
<button @click="openRcloneConfig" class="action-btn config-btn">
|
||||
<button class="action-btn config-btn" @click="openRcloneConfig">
|
||||
<Settings :size="18" />
|
||||
<span>{{ t('dashboard.quickActions.configRclone') }}</span>
|
||||
</button>
|
||||
|
||||
<button @click="viewMounts" class="action-btn mount-btn">
|
||||
<button class="action-btn mount-btn" @click="viewMounts">
|
||||
<HardDrive :size="18" />
|
||||
<span>{{ t('dashboard.quickActions.manageMounts') }}</span>
|
||||
</button>
|
||||
@@ -104,14 +104,13 @@
|
||||
</div>
|
||||
<div class="settings-toggles">
|
||||
<label class="toggle-item">
|
||||
<input type="checkbox" v-model="settings.openlist.auto_launch" @change="handleAutoLaunchToggle" />
|
||||
<input v-model="settings.openlist.auto_launch" type="checkbox" @change="handleAutoLaunchToggle" />
|
||||
<span class="toggle-text">{{ t('dashboard.quickActions.autoLaunch') }}</span>
|
||||
</label>
|
||||
|
||||
<!-- Windows Firewall Management-->
|
||||
<button
|
||||
v-if="isWindows"
|
||||
@click="toggleFirewallRule"
|
||||
:class="['firewall-toggle-btn', { active: firewallEnabled }]"
|
||||
:disabled="firewallLoading"
|
||||
:title="
|
||||
@@ -119,6 +118,7 @@
|
||||
? t('dashboard.quickActions.firewall.disable')
|
||||
: t('dashboard.quickActions.firewall.enable')
|
||||
"
|
||||
@click="toggleFirewallRule"
|
||||
>
|
||||
<Shield :size="18" />
|
||||
<span>
|
||||
@@ -136,14 +136,16 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ExternalLink, HardDrive, Key, Loader, Play, RotateCcw, Settings, Shield, Square } from 'lucide-vue-next'
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import { TauriAPI } from '@/api/tauri'
|
||||
|
||||
import { useTranslation } from '../../composables/useI18n'
|
||||
import { useAppStore } from '../../stores/app'
|
||||
import { useRcloneStore } from '../../stores/rclone'
|
||||
import { useTranslation } from '../../composables/useI18n'
|
||||
import Card from '../ui/Card.vue'
|
||||
import { Play, Square, RotateCcw, ExternalLink, Settings, HardDrive, Key, Shield, Loader } from 'lucide-vue-next'
|
||||
import { TauriAPI } from '@/api/tauri'
|
||||
import Card from '../ui/CardPage.vue'
|
||||
|
||||
const { t } = useTranslation()
|
||||
const router = useRouter()
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
<div class="actions-section">
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
@click="installService"
|
||||
v-if="serviceStatus !== 'running' && serviceStatus !== 'stopped'"
|
||||
:disabled="actionLoading || serviceStatus === 'installed'"
|
||||
class="action-btn install-btn"
|
||||
v-if="serviceStatus !== 'running' && serviceStatus !== 'stopped'"
|
||||
@click="installService"
|
||||
>
|
||||
<component :is="actionLoading && currentAction === 'install' ? LoaderIcon : Download" :size="16" />
|
||||
<span>{{
|
||||
@@ -33,10 +33,10 @@
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="startService"
|
||||
v-if="serviceStatus === 'installed' || serviceStatus === 'stopped'"
|
||||
:disabled="actionLoading || (serviceStatus !== 'installed' && serviceStatus !== 'stopped')"
|
||||
class="action-btn start-btn"
|
||||
v-if="serviceStatus === 'installed' || serviceStatus === 'stopped'"
|
||||
@click="startService"
|
||||
>
|
||||
<component :is="actionLoading && currentAction === 'start' ? LoaderIcon : Play" :size="16" />
|
||||
<span>{{
|
||||
@@ -45,10 +45,10 @@
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="stopService"
|
||||
v-if="serviceStatus === 'running'"
|
||||
:disabled="actionLoading"
|
||||
class="action-btn stop-btn"
|
||||
v-if="serviceStatus === 'running'"
|
||||
@click="stopService"
|
||||
>
|
||||
<component :is="actionLoading && currentAction === 'stop' ? LoaderIcon : Stop" :size="16" />
|
||||
<span>{{
|
||||
@@ -57,10 +57,10 @@
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="showUninstallDialog = true"
|
||||
v-if="serviceStatus !== 'not-installed'"
|
||||
:disabled="actionLoading"
|
||||
class="action-btn uninstall-btn"
|
||||
v-if="serviceStatus !== 'not-installed'"
|
||||
@click="showUninstallDialog = true"
|
||||
>
|
||||
<component :is="actionLoading && currentAction === 'uninstall' ? LoaderIcon : Trash2" :size="16" />
|
||||
<span>{{
|
||||
@@ -87,24 +87,26 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||
import { useTranslation } from '../../composables/useI18n'
|
||||
import {
|
||||
CheckCircle2,
|
||||
Circle,
|
||||
Download,
|
||||
Loader2 as LoaderIcon,
|
||||
Play,
|
||||
Server,
|
||||
Square as Stop,
|
||||
Trash2,
|
||||
Loader2 as LoaderIcon,
|
||||
CheckCircle2,
|
||||
XCircle,
|
||||
Circle,
|
||||
Server
|
||||
XCircle
|
||||
} from 'lucide-vue-next'
|
||||
import Card from '../ui/Card.vue'
|
||||
import ConfirmDialog from '../ui/ConfirmDialog.vue'
|
||||
import { TauriAPI } from '../../api/tauri'
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
|
||||
import { useRcloneStore } from '@/stores/rclone'
|
||||
|
||||
import { TauriAPI } from '../../api/tauri'
|
||||
import { useTranslation } from '../../composables/useI18n'
|
||||
import Card from '../ui/CardPage.vue'
|
||||
import ConfirmDialog from '../ui/ConfirmDialog.vue'
|
||||
|
||||
const rcloneStore = useRcloneStore()
|
||||
|
||||
const { t } = useTranslation()
|
||||
@@ -114,7 +116,7 @@ const actionLoading = ref(false)
|
||||
const currentAction = ref('')
|
||||
const showUninstallDialog = ref(false)
|
||||
|
||||
let statusCheckInterval: number | null = null
|
||||
const statusCheckInterval: number | null = null
|
||||
|
||||
const statusClass = computed(() => {
|
||||
switch (serviceStatus.value) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<template>
|
||||
<Card
|
||||
:title="t('update.title')"
|
||||
@@ -12,7 +13,7 @@
|
||||
<h4>{{ t('update.currentVersion') }}</h4>
|
||||
<span class="version-tag">v{{ currentVersion }}</span>
|
||||
</div>
|
||||
<button @click="checkForUpdates" :disabled="checking || downloading || installing" class="check-update-btn">
|
||||
<button :disabled="checking || downloading || installing" class="check-update-btn" @click="checkForUpdates">
|
||||
<RefreshCw :size="16" />
|
||||
{{ checking ? t('update.checking') : t('update.checkForUpdates') }}
|
||||
</button>
|
||||
@@ -21,7 +22,7 @@
|
||||
<div class="settings-row">
|
||||
<div class="auto-check-setting">
|
||||
<label class="checkbox-container">
|
||||
<input type="checkbox" v-model="autoCheckEnabled" @change="toggleAutoCheck" :disabled="settingsLoading" />
|
||||
<input v-model="autoCheckEnabled" type="checkbox" :disabled="settingsLoading" @change="toggleAutoCheck" />
|
||||
<span class="label-text">{{ t('update.autoCheck') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
@@ -32,7 +33,7 @@
|
||||
<AlertCircle :size="16" />
|
||||
<span>{{ error }}</span>
|
||||
</div>
|
||||
<button @click="clearError" class="clear-error-btn">×</button>
|
||||
<button class="clear-error-btn" @click="clearError">×</button>
|
||||
</div>
|
||||
|
||||
<div v-if="!updateCheck?.hasUpdate && lastChecked && !checking && !error" class="no-updates">
|
||||
@@ -100,11 +101,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="update-actions" v-if="!downloading">
|
||||
<div v-if="!downloading" class="update-actions">
|
||||
<button
|
||||
@click="downloadAndInstall"
|
||||
:disabled="!selectedAsset || checking || downloading || installing"
|
||||
class="install-btn"
|
||||
@click="downloadAndInstall"
|
||||
>
|
||||
<Download :size="16" />
|
||||
{{ t('update.downloadAndInstall') }}
|
||||
@@ -124,7 +125,7 @@
|
||||
<Info :size="20" class="notification-icon" />
|
||||
<div class="notification-text">
|
||||
<span>{{ t('update.backgroundUpdateAvailable') }}</span>
|
||||
<button @click="showBackgroundUpdate" class="show-update-btn">
|
||||
<button class="show-update-btn" @click="showBackgroundUpdate">
|
||||
{{ t('update.showUpdate') }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -135,13 +136,15 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, computed } from 'vue'
|
||||
import { AlertCircle, ArrowRight, CheckCircle, CheckCircle2, Download, Info, RefreshCw } from 'lucide-vue-next'
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
|
||||
import { formatBytes } from '@/utils/formatters'
|
||||
|
||||
import { TauriAPI } from '../../api/tauri'
|
||||
import { useTranslation } from '../../composables/useI18n'
|
||||
import { useAppStore } from '../../stores/app'
|
||||
import { TauriAPI } from '../../api/tauri'
|
||||
import Card from '../ui/Card.vue'
|
||||
import { formatBytes } from '@/utils/formatters'
|
||||
import { RefreshCw, Download, ArrowRight, CheckCircle, AlertCircle, Info, CheckCircle2 } from 'lucide-vue-next'
|
||||
import Card from '../ui/CardPage.vue'
|
||||
|
||||
interface Props {
|
||||
isStandalone?: boolean
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<h4>{{ t('dashboard.versionManager.openlist') }}</h4>
|
||||
<span class="current-version">{{ currentVersions.openlist }}</span>
|
||||
</div>
|
||||
<button @click="refreshVersions" :disabled="refreshing" class="refresh-icon-btn">
|
||||
<button :disabled="refreshing" class="refresh-icon-btn" @click="refreshVersions">
|
||||
<component
|
||||
:is="refreshing ? Loader : RefreshCw"
|
||||
:size="16"
|
||||
@@ -24,11 +24,11 @@
|
||||
</option>
|
||||
</select>
|
||||
<button
|
||||
@click="updateVersion('openlist')"
|
||||
:disabled="
|
||||
!selectedVersions.openlist || loading.openlist || selectedVersions.openlist === currentVersions.openlist
|
||||
"
|
||||
class="update-btn"
|
||||
@click="updateVersion('openlist')"
|
||||
>
|
||||
<component :is="loading.openlist ? Loader : Download" :size="14" />
|
||||
<span>{{
|
||||
@@ -43,7 +43,7 @@
|
||||
<h4>{{ t('dashboard.versionManager.rclone') }}</h4>
|
||||
<span class="current-version">{{ currentVersions.rclone }}</span>
|
||||
</div>
|
||||
<button @click="refreshVersions" :disabled="refreshing" class="refresh-icon-btn">
|
||||
<button :disabled="refreshing" class="refresh-icon-btn" @click="refreshVersions">
|
||||
<component
|
||||
:is="refreshing ? Loader : RefreshCw"
|
||||
:size="16"
|
||||
@@ -59,11 +59,11 @@
|
||||
</option>
|
||||
</select>
|
||||
<button
|
||||
@click="updateVersion('rclone')"
|
||||
:disabled="
|
||||
!selectedVersions.rclone || loading.rclone || selectedVersions.rclone === currentVersions.rclone
|
||||
"
|
||||
class="update-btn"
|
||||
@click="updateVersion('rclone')"
|
||||
>
|
||||
<component :is="loading.rclone ? Loader : Download" :size="14" />
|
||||
<span>{{
|
||||
@@ -78,11 +78,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useTranslation } from '../../composables/useI18n'
|
||||
import { Download, RefreshCw, Loader } from 'lucide-vue-next'
|
||||
import Card from '../ui/Card.vue'
|
||||
import { Download, Loader, RefreshCw } from 'lucide-vue-next'
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
import { TauriAPI } from '../../api/tauri'
|
||||
import { useTranslation } from '../../composables/useI18n'
|
||||
import Card from '../ui/CardPage.vue'
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ interface Props {
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
title: '',
|
||||
variant: 'default',
|
||||
hover: false,
|
||||
interactive: false
|
||||
@@ -8,10 +8,10 @@
|
||||
<p class="dialog-message">{{ message }}</p>
|
||||
</div>
|
||||
<div class="dialog-actions">
|
||||
<button @click="onCancel" class="dialog-btn cancel-btn">
|
||||
<button class="dialog-btn cancel-btn" @click="onCancel">
|
||||
{{ cancelText }}
|
||||
</button>
|
||||
<button @click="onConfirm" class="dialog-btn confirm-btn" :class="confirmButtonClass">
|
||||
<button class="dialog-btn confirm-btn" :class="confirmButtonClass" @click="onConfirm">
|
||||
{{ confirmText }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -79,7 +79,9 @@ export default {
|
||||
.dialog-container {
|
||||
background: white;
|
||||
border-radius: 0.75rem;
|
||||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||
box-shadow:
|
||||
0 20px 25px -5px rgba(0, 0, 0, 0.1),
|
||||
0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||
max-width: 28rem;
|
||||
width: 90%;
|
||||
max-height: 80vh;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useTranslation } from '../../composables/useI18n'
|
||||
import { ChevronDown } from 'lucide-vue-next'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
|
||||
import { useTranslation } from '../../composables/useI18n'
|
||||
|
||||
const { currentLocale, switchLanguage } = useTranslation()
|
||||
const isOpen = ref(false)
|
||||
@@ -35,7 +36,7 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<div ref="dropdownRef" class="language-switcher relative">
|
||||
<button @click="toggleDropdown" class="language-button">
|
||||
<button class="language-button" @click="toggleDropdown">
|
||||
<span class="language-label">{{ currentLanguage?.name }}</span>
|
||||
<ChevronDown :size="12" :class="{ flipped: isOpen }" />
|
||||
</button>
|
||||
@@ -44,9 +45,9 @@ onMounted(() => {
|
||||
<div
|
||||
v-for="language in languages"
|
||||
:key="language.code"
|
||||
@click="handleLanguageChange(language.code)"
|
||||
class="language-option"
|
||||
:class="{ active: language.code === currentLocale }"
|
||||
@click="handleLanguageChange(language.code)"
|
||||
>
|
||||
<span class="language-flag">{{ language.flag }}</span>
|
||||
<span class="language-name">{{ language.name }}</span>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { Monitor, Moon, Sun } from 'lucide-vue-next'
|
||||
import { computed } from 'vue'
|
||||
import { useAppStore } from '../../stores/app'
|
||||
|
||||
import { useTranslation } from '../../composables/useI18n'
|
||||
import { Sun, Moon, Monitor } from 'lucide-vue-next'
|
||||
import { useAppStore } from '../../stores/app'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const { t } = useTranslation()
|
||||
@@ -41,7 +42,7 @@ const toggleTheme = () => {
|
||||
|
||||
<template>
|
||||
<div class="theme-switcher">
|
||||
<button @click="toggleTheme" class="theme-toggle-btn" :title="t('settings.theme.toggle')">
|
||||
<button class="theme-toggle-btn" :title="t('settings.theme.toggle')" @click="toggleTheme">
|
||||
<component :is="currentThemeOption.icon" :size="18" />
|
||||
<span class="theme-label">{{ currentThemeOption.label }}</span>
|
||||
</button>
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
|
||||
import WindowControls from './WindowControls.vue'
|
||||
interface Props {
|
||||
appTitle?: string
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
<div v-if="message" class="notification-message">{{ message }}</div>
|
||||
</div>
|
||||
<div class="notification-actions">
|
||||
<button v-if="showAction" @click="$emit('action')" class="action-btn">
|
||||
<button v-if="showAction" class="action-btn" @click="$emit('action')">
|
||||
{{ actionText }}
|
||||
</button>
|
||||
<button @click="$emit('dismiss')" class="dismiss-btn">
|
||||
<button class="dismiss-btn" @click="$emit('dismiss')">
|
||||
<X :size="16" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -23,13 +23,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Download, CheckCircle, AlertCircle, X } from 'lucide-vue-next'
|
||||
import { AlertCircle, CheckCircle, Download, X } from 'lucide-vue-next'
|
||||
|
||||
interface Props {
|
||||
visible: boolean
|
||||
type: 'info' | 'success' | 'warning' | 'error'
|
||||
type?: 'info' | 'success' | 'warning' | 'error'
|
||||
title: string
|
||||
message?: string
|
||||
message: string
|
||||
showAction?: boolean
|
||||
actionText?: string
|
||||
}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
<template>
|
||||
<div class="window-controls">
|
||||
<button class="control-btn minimize" @click="$emit('minimize')" :title="t('common.minimize')">
|
||||
<button class="control-btn minimize" :title="t('common.minimize')" @click="$emit('minimize')">
|
||||
<Minimize2 :size="12" />
|
||||
</button>
|
||||
<button class="control-btn maximize" @click="$emit('maximize')" :title="t('common.maximize')">
|
||||
<button class="control-btn maximize" :title="t('common.maximize')" @click="$emit('maximize')">
|
||||
<Maximize2 :size="12" />
|
||||
</button>
|
||||
<button class="control-btn close" @click="$emit('close')" :title="t('common.close')">
|
||||
<button class="control-btn close" :title="t('common.close')" @click="$emit('close')">
|
||||
<X :size="12" />
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Minimize2, Maximize2, X } from 'lucide-vue-next'
|
||||
import { Maximize2, Minimize2, X } from 'lucide-vue-next'
|
||||
|
||||
import { useTranslation } from '../../composables/useI18n'
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, computed } from 'vue'
|
||||
import { useAppStore } from '../stores/app'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
|
||||
import QuickActionsCard from '../components/dashboard/QuickActionsCard.vue'
|
||||
import CoreMonitorCard from '../components/dashboard/CoreMonitorCard.vue'
|
||||
import VersionManagerCard from '../components/dashboard/VersionManagerCard.vue'
|
||||
import DocumentationCard from '../components/dashboard/DocumentationCard.vue'
|
||||
import QuickActionsCard from '../components/dashboard/QuickActionsCard.vue'
|
||||
import ServiceManagementCard from '../components/dashboard/ServiceManagementCard.vue'
|
||||
import VersionManagerCard from '../components/dashboard/VersionManagerCard.vue'
|
||||
import { useAppStore } from '../stores/app'
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue'
|
||||
import { useAppStore } from '../stores/app'
|
||||
import { useTranslation } from '../composables/useI18n'
|
||||
import * as chrono from 'chrono-node'
|
||||
import {
|
||||
Search,
|
||||
Filter,
|
||||
Download,
|
||||
Copy,
|
||||
Trash2,
|
||||
Play,
|
||||
Pause,
|
||||
RotateCcw,
|
||||
Settings,
|
||||
ArrowUp,
|
||||
AlertCircle,
|
||||
AlertTriangle,
|
||||
ArrowDown,
|
||||
ArrowUp,
|
||||
Copy,
|
||||
Download,
|
||||
Filter,
|
||||
FolderOpen,
|
||||
Info,
|
||||
Maximize2,
|
||||
Minimize2,
|
||||
AlertCircle,
|
||||
Info,
|
||||
AlertTriangle,
|
||||
FolderOpen
|
||||
Pause,
|
||||
Play,
|
||||
RotateCcw,
|
||||
Search,
|
||||
Settings,
|
||||
Trash2
|
||||
} from 'lucide-vue-next'
|
||||
import * as chrono from 'chrono-node'
|
||||
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
|
||||
import ConfirmDialog from '../components/ui/ConfirmDialog.vue'
|
||||
import { useTranslation } from '../composables/useI18n'
|
||||
import { useAppStore } from '../stores/app'
|
||||
|
||||
type filterSourceType = 'openlist' | 'rclone' | 'app' | 'service' | 'all'
|
||||
|
||||
@@ -420,14 +421,14 @@ onUnmounted(() => {
|
||||
<button
|
||||
class="toolbar-btn"
|
||||
:class="{ active: isPaused }"
|
||||
@click="togglePause"
|
||||
:title="isPaused ? t('logs.toolbar.resume') : t('logs.toolbar.pause')"
|
||||
@click="togglePause"
|
||||
>
|
||||
<Pause v-if="!isPaused" :size="16" />
|
||||
<Play v-else :size="16" />
|
||||
</button>
|
||||
|
||||
<button class="toolbar-btn" @click="refreshLogs" :title="t('logs.toolbar.refresh')">
|
||||
<button class="toolbar-btn" :title="t('logs.toolbar.refresh')" @click="refreshLogs">
|
||||
<RotateCcw :size="16" />
|
||||
</button>
|
||||
|
||||
@@ -436,8 +437,8 @@ onUnmounted(() => {
|
||||
<button
|
||||
class="toolbar-btn"
|
||||
:class="{ active: showFilters }"
|
||||
@click="showFilters = !showFilters"
|
||||
:title="t('logs.toolbar.showFilters')"
|
||||
@click="showFilters = !showFilters"
|
||||
>
|
||||
<Filter :size="16" />
|
||||
</button>
|
||||
@@ -445,8 +446,8 @@ onUnmounted(() => {
|
||||
<button
|
||||
class="toolbar-btn"
|
||||
:class="{ active: showSettings }"
|
||||
@click="showSettings = !showSettings"
|
||||
:title="t('logs.toolbar.settings')"
|
||||
@click="showSettings = !showSettings"
|
||||
>
|
||||
<Settings :size="16" />
|
||||
</button>
|
||||
@@ -480,38 +481,38 @@ onUnmounted(() => {
|
||||
|
||||
<button
|
||||
class="toolbar-btn"
|
||||
@click="copyLogsToClipboard"
|
||||
:title="t('logs.toolbar.copyToClipboard')"
|
||||
:disabled="filteredLogs.length === 0"
|
||||
@click="copyLogsToClipboard"
|
||||
>
|
||||
<Copy :size="16" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="toolbar-btn"
|
||||
@click="exportLogs"
|
||||
:title="t('logs.toolbar.exportLogs')"
|
||||
:disabled="filteredLogs.length === 0"
|
||||
@click="exportLogs"
|
||||
>
|
||||
<Download :size="16" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="toolbar-btn danger"
|
||||
@click="clearLogs"
|
||||
:disabled="filteredLogs.length === 0 || filterSource === 'gin' || filterSource === 'all'"
|
||||
:title="t('logs.toolbar.clearLogs')"
|
||||
@click="clearLogs"
|
||||
>
|
||||
<Trash2 :size="16" />
|
||||
</button>
|
||||
|
||||
<button class="toolbar-btn" @click="openLogsDirectory" :title="t('logs.toolbar.openLogsDirectory')">
|
||||
<button class="toolbar-btn" :title="t('logs.toolbar.openLogsDirectory')" @click="openLogsDirectory">
|
||||
<FolderOpen :size="16" />
|
||||
</button>
|
||||
|
||||
<div class="toolbar-separator"></div>
|
||||
|
||||
<button class="toolbar-btn" @click="toggleFullscreen" :title="t('logs.toolbar.toggleFullscreen')">
|
||||
<button class="toolbar-btn" :title="t('logs.toolbar.toggleFullscreen')" @click="toggleFullscreen">
|
||||
<Maximize2 v-if="!isFullscreen" :size="16" />
|
||||
<Minimize2 v-else :size="16" />
|
||||
</button>
|
||||
@@ -542,11 +543,11 @@ onUnmounted(() => {
|
||||
</div>
|
||||
|
||||
<div class="filter-actions">
|
||||
<button class="filter-btn" @click="selectAllVisible" :disabled="filteredLogs.length === 0">
|
||||
<button class="filter-btn" :disabled="filteredLogs.length === 0" @click="selectAllVisible">
|
||||
{{ t('logs.filters.actions.selectAll') }}
|
||||
</button>
|
||||
|
||||
<button class="filter-btn" @click="clearSelection" :disabled="selectedEntries.size === 0">
|
||||
<button class="filter-btn" :disabled="selectedEntries.size === 0" @click="clearSelection">
|
||||
{{ t('logs.filters.actions.clearSelection') }}
|
||||
</button>
|
||||
|
||||
@@ -587,10 +588,10 @@ onUnmounted(() => {
|
||||
<div class="log-col source">{{ t('logs.headers.source') }}</div>
|
||||
<div class="log-col message">{{ t('logs.headers.message') }}</div>
|
||||
<div class="log-col actions">
|
||||
<button class="scroll-btn" @click="scrollToTop" :title="t('logs.toolbar.scrollToTop')">
|
||||
<button class="scroll-btn" :title="t('logs.toolbar.scrollToTop')" @click="scrollToTop">
|
||||
<ArrowUp :size="14" />
|
||||
</button>
|
||||
<button class="scroll-btn" @click="scrollToBottom" :title="t('logs.toolbar.scrollToBottom')">
|
||||
<button class="scroll-btn" :title="t('logs.toolbar.scrollToBottom')" @click="scrollToBottom">
|
||||
<ArrowDown :size="14" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onUnmounted, ComputedRef, Ref } from 'vue'
|
||||
import { useTranslation } from '../composables/useI18n'
|
||||
import { useRcloneStore } from '../stores/rclone'
|
||||
import {
|
||||
HardDrive,
|
||||
Plus,
|
||||
Edit,
|
||||
Trash2,
|
||||
Play,
|
||||
Square,
|
||||
CheckCircle,
|
||||
XCircle,
|
||||
Loader,
|
||||
Cloud,
|
||||
Search,
|
||||
Edit,
|
||||
FolderOpen,
|
||||
HardDrive,
|
||||
Loader,
|
||||
Play,
|
||||
Plus,
|
||||
RefreshCw,
|
||||
Save,
|
||||
X,
|
||||
Search,
|
||||
Settings,
|
||||
FolderOpen
|
||||
Square,
|
||||
Trash2,
|
||||
X,
|
||||
XCircle
|
||||
} from 'lucide-vue-next'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import { computed, ComputedRef, onMounted, onUnmounted, Ref, ref } from 'vue'
|
||||
|
||||
import ConfirmDialog from '@/components/ui/ConfirmDialog.vue'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
|
||||
import { useTranslation } from '../composables/useI18n'
|
||||
import { useRcloneStore } from '../stores/rclone'
|
||||
|
||||
const { t } = useTranslation()
|
||||
const rcloneStore = useRcloneStore()
|
||||
@@ -127,7 +129,7 @@ const commonFlags = ref([
|
||||
const showFlagSelector = ref(false)
|
||||
|
||||
const filteredConfigs: ComputedRef<RcloneFormConfig[]> = computed(() => {
|
||||
let filtered: RcloneFormConfig[] = []
|
||||
const filtered: RcloneFormConfig[] = []
|
||||
const fullRemoteConfigs = appStore.fullRcloneConfigs
|
||||
|
||||
for (const config of fullRemoteConfigs) {
|
||||
@@ -456,7 +458,7 @@ const dismissWebdavTip = () => {
|
||||
const isWindows = computed(() => {
|
||||
return typeof OS_PLATFORM !== 'undefined' && OS_PLATFORM === 'win32'
|
||||
})
|
||||
const showWinfspTip = ref(isWindows && !localStorage.getItem('winfsp_tip_dismissed'))
|
||||
const showWinfspTip = ref(isWindows.value && !localStorage.getItem('winfsp_tip_dismissed'))
|
||||
|
||||
const dismissWinfspTip = () => {
|
||||
showWinfspTip.value = false
|
||||
@@ -464,7 +466,7 @@ const dismissWinfspTip = () => {
|
||||
}
|
||||
|
||||
const shouldShowWebdavTip = computed(() => {
|
||||
if (isWindows) {
|
||||
if (isWindows.value) {
|
||||
return !showWinfspTip.value && showWebdavTip.value
|
||||
}
|
||||
return showWebdavTip.value
|
||||
@@ -533,14 +535,14 @@ onUnmounted(() => {
|
||||
{{ rcloneStore.serviceRunning ? t('mount.service.running') : t('mount.service.stopped') }}
|
||||
</span>
|
||||
<button
|
||||
@click="rcloneStore.serviceRunning ? stopBackend() : startBackend()"
|
||||
:class="['service-toggle', { active: rcloneStore.serviceRunning }]"
|
||||
:disabled="rcloneStore.loading"
|
||||
@click="rcloneStore.serviceRunning ? stopBackend() : startBackend()"
|
||||
>
|
||||
<component :is="rcloneStore.serviceRunning ? Square : Play" class="btn-icon" />
|
||||
</button>
|
||||
</div>
|
||||
<button @click="addNewConfig" class="primary-btn">
|
||||
<button class="primary-btn" @click="addNewConfig">
|
||||
<Plus class="btn-icon" />
|
||||
<span>{{ t('mount.actions.addRemote') }}</span>
|
||||
</button>
|
||||
@@ -557,7 +559,7 @@ onUnmounted(() => {
|
||||
<h4 class="tip-title">{{ t('mount.tip.webdavTitle') }}</h4>
|
||||
<p class="tip-description">{{ t('mount.tip.webdavMessage') }}</p>
|
||||
</div>
|
||||
<button @click="dismissWebdavTip" class="tip-close" :title="t('mount.tip.dismissForever')">
|
||||
<button class="tip-close" :title="t('mount.tip.dismissForever')" @click="dismissWebdavTip">
|
||||
<X class="close-icon" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -572,7 +574,7 @@ onUnmounted(() => {
|
||||
<h4 class="tip-title">{{ t('mount.tip.winfspTitle') }}</h4>
|
||||
<p class="tip-description">{{ t('mount.tip.winfspMessage') }}</p>
|
||||
</div>
|
||||
<button @click="dismissWinfspTip" class="tip-close" :title="t('mount.tip.dismissForever')">
|
||||
<button class="tip-close" :title="t('mount.tip.dismissForever')" @click="dismissWinfspTip">
|
||||
<X class="close-icon" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -596,7 +598,7 @@ onUnmounted(() => {
|
||||
<option value="unmounted">{{ t('mount.status.unmounted') }}</option>
|
||||
<option value="error">{{ t('mount.status.error') }}</option>
|
||||
</select>
|
||||
<button @click="appStore.loadMountInfos" class="refresh-btn" :disabled="rcloneStore.loading">
|
||||
<button class="refresh-btn" :disabled="rcloneStore.loading" @click="appStore.loadMountInfos">
|
||||
<RefreshCw class="refresh-icon" :class="{ spinning: rcloneStore.loading }" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -605,7 +607,7 @@ onUnmounted(() => {
|
||||
<div v-if="rcloneStore.error" class="error-alert">
|
||||
<XCircle class="alert-icon" />
|
||||
<span class="alert-message">{{ rcloneStore.error }}</span>
|
||||
<button @click="rcloneStore.clearError" class="alert-close">
|
||||
<button class="alert-close" @click="rcloneStore.clearError">
|
||||
<X class="close-icon" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -617,7 +619,7 @@ onUnmounted(() => {
|
||||
<Cloud class="empty-icon" />
|
||||
<h3 class="empty-title">{{ t('mount.empty.title') }}</h3>
|
||||
<p class="empty-description">{{ t('mount.empty.description') }}</p>
|
||||
<button @click="addNewConfig" class="empty-action-btn">
|
||||
<button class="empty-action-btn" @click="addNewConfig">
|
||||
<Plus class="btn-icon" />
|
||||
<span>{{ t('mount.actions.addRemote') }}</span>
|
||||
</button>
|
||||
@@ -664,8 +666,8 @@ onUnmounted(() => {
|
||||
<span
|
||||
v-if="config.mountPoint"
|
||||
class="meta-tag clickable-mount-point"
|
||||
@click="openInFileExplorer(config.mountPoint)"
|
||||
:title="t('mount.meta.openInExplorer')"
|
||||
@click="openInFileExplorer(config.mountPoint)"
|
||||
>
|
||||
<FolderOpen class="mount-point-icon" />
|
||||
{{ config.mountPoint }}
|
||||
@@ -679,19 +681,19 @@ onUnmounted(() => {
|
||||
<div class="action-group">
|
||||
<button
|
||||
v-if="!isConfigMounted(config)"
|
||||
@click="mountConfig(config)"
|
||||
class="action-btn primary"
|
||||
:disabled="isConfigMounting(config) || !config.mountPoint"
|
||||
:title="!config.mountPoint ? t('mount.messages.mountPointRequired') : ''"
|
||||
@click="mountConfig(config)"
|
||||
>
|
||||
<Play class="btn-icon" />
|
||||
<span>{{ t('mount.actions.mount') }}</span>
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
@click="unmountConfig(config)"
|
||||
class="action-btn warning"
|
||||
:disabled="isConfigMounting(config)"
|
||||
@click="unmountConfig(config)"
|
||||
>
|
||||
<Square class="btn-icon" />
|
||||
<span>{{ t('mount.actions.unmount') }}</span>
|
||||
@@ -699,22 +701,22 @@ onUnmounted(() => {
|
||||
</div>
|
||||
|
||||
<div class="secondary-actions">
|
||||
<button @click="editConfig(config)" class="secondary-btn" :title="t('mount.actions.edit')">
|
||||
<button class="secondary-btn" :title="t('mount.actions.edit')" @click="editConfig(config)">
|
||||
<Edit class="btn-icon" />
|
||||
</button>
|
||||
<button
|
||||
@click="deleteConfig(config)"
|
||||
class="secondary-btn danger"
|
||||
:disabled="isConfigMounted(config)"
|
||||
:title="t('mount.actions.delete')"
|
||||
@click="deleteConfig(config)"
|
||||
>
|
||||
<Trash2 class="btn-icon" />
|
||||
</button>
|
||||
<button
|
||||
v-if="isConfigMounted(config)"
|
||||
@click="openInFileExplorer(config.mountPoint)"
|
||||
class="secondary-btn"
|
||||
:title="t('mount.actions.openInExplorer')"
|
||||
@click="openInFileExplorer(config.mountPoint)"
|
||||
>
|
||||
<FolderOpen class="btn-icon" />
|
||||
</button>
|
||||
@@ -733,7 +735,7 @@ onUnmounted(() => {
|
||||
{{ editingConfig ? t('mount.config.editTitle') : t('mount.config.addTitle') }}
|
||||
</h2>
|
||||
</div>
|
||||
<button @click="cancelForm" class="modal-close">
|
||||
<button class="modal-close" @click="cancelForm">
|
||||
<X class="close-icon" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -847,10 +849,10 @@ onUnmounted(() => {
|
||||
|
||||
<div class="flags-header">
|
||||
<button
|
||||
@click="showFlagSelector = !showFlagSelector"
|
||||
type="button"
|
||||
class="quick-flags-btn"
|
||||
:title="t('mount.config.quickFlagsTooltip')"
|
||||
@click="showFlagSelector = !showFlagSelector"
|
||||
>
|
||||
<Settings class="btn-icon" />
|
||||
<span>{{ t('mount.config.quickFlags') }}</span>
|
||||
@@ -861,7 +863,7 @@ onUnmounted(() => {
|
||||
<div class="flag-selector-popup" @click.stop>
|
||||
<div class="flag-selector-header">
|
||||
<h4>{{ t('mount.config.selectCommonFlags') }}</h4>
|
||||
<button @click="closeFlagSelector" class="close-selector-btn">
|
||||
<button class="close-selector-btn" @click="closeFlagSelector">
|
||||
<X class="btn-icon" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -880,13 +882,13 @@ onUnmounted(() => {
|
||||
<div
|
||||
v-for="flag in category.flags"
|
||||
:key="`${flag.flag}-${flag.value}`"
|
||||
@click="toggleFlag(flag)"
|
||||
class="flag-option"
|
||||
:class="{
|
||||
selected: isFlagInConfig(flag),
|
||||
'in-config': isFlagInConfig(flag)
|
||||
}"
|
||||
:title="getFlagDescription(flag)"
|
||||
@click="toggleFlag(flag)"
|
||||
>
|
||||
<div class="flag-checkbox">
|
||||
<div class="custom-checkbox" :class="{ checked: isFlagInConfig(flag) }">
|
||||
@@ -915,15 +917,15 @@ onUnmounted(() => {
|
||||
:placeholder="t('mount.config.flagPlaceholder')"
|
||||
/>
|
||||
<button
|
||||
@click="removeFlag(index)"
|
||||
type="button"
|
||||
class="remove-flag-btn"
|
||||
:title="t('mount.config.removeFlag')"
|
||||
@click="removeFlag(index)"
|
||||
>
|
||||
<X class="btn-icon" />
|
||||
</button>
|
||||
</div>
|
||||
<button @click="addFlag" type="button" class="add-flag-btn">
|
||||
<button type="button" class="add-flag-btn" @click="addFlag">
|
||||
<Plus class="btn-icon" />
|
||||
<span>{{ t('mount.config.addFlag') }}</span>
|
||||
</button>
|
||||
@@ -934,11 +936,11 @@ onUnmounted(() => {
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button @click="cancelForm" class="cancel-btn">
|
||||
<button class="cancel-btn" @click="cancelForm">
|
||||
<X class="btn-icon" />
|
||||
<span>{{ t('common.cancel') }}</span>
|
||||
</button>
|
||||
<button @click="saveConfig" class="save-btn" :disabled="appStore.loading">
|
||||
<button class="save-btn" :disabled="appStore.loading" @click="saveConfig">
|
||||
<Save class="btn-icon" />
|
||||
<span>{{ editingConfig ? t('common.save') : t('common.add') }}</span>
|
||||
</button>
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useAppStore } from '../stores/app'
|
||||
import { useTranslation } from '../composables/useI18n'
|
||||
import { disable, enable, isEnabled } from '@tauri-apps/plugin-autostart'
|
||||
import { open } from '@tauri-apps/plugin-dialog'
|
||||
import {
|
||||
Settings,
|
||||
Server,
|
||||
HardDrive,
|
||||
Save,
|
||||
RotateCcw,
|
||||
AlertCircle,
|
||||
CheckCircle,
|
||||
ExternalLink,
|
||||
FolderOpen,
|
||||
ExternalLink
|
||||
HardDrive,
|
||||
RotateCcw,
|
||||
Save,
|
||||
Server,
|
||||
Settings
|
||||
} from 'lucide-vue-next'
|
||||
import { enable, isEnabled, disable } from '@tauri-apps/plugin-autostart'
|
||||
import { open } from '@tauri-apps/plugin-dialog'
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import ConfirmDialog from '../components/ui/ConfirmDialog.vue'
|
||||
import { useTranslation } from '../composables/useI18n'
|
||||
import { useAppStore } from '../stores/app'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const route = useRoute()
|
||||
@@ -335,11 +336,11 @@ const loadCurrentAdminPassword = async () => {
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button @click="handleReset" class="btn btn-secondary" :title="t('settings.resetToDefaults')">
|
||||
<button class="btn btn-secondary" :title="t('settings.resetToDefaults')" @click="handleReset">
|
||||
<RotateCcw :size="16" />
|
||||
{{ t('common.reset') }}
|
||||
</button>
|
||||
<button @click="handleSave" :disabled="!hasUnsavedChanges || isSaving" class="btn btn-primary">
|
||||
<button :disabled="!hasUnsavedChanges || isSaving" class="btn btn-primary" @click="handleSave">
|
||||
<Save :size="16" />
|
||||
{{ isSaving ? t('common.saving') : t('settings.saveChanges') }}
|
||||
</button>
|
||||
@@ -349,16 +350,16 @@ const loadCurrentAdminPassword = async () => {
|
||||
<div v-if="message" class="message-banner" :class="messageType">
|
||||
<component :is="messageType === 'success' ? CheckCircle : AlertCircle" :size="16" />
|
||||
<span>{{ message }}</span>
|
||||
<button @click="message = ''" class="message-close">×</button>
|
||||
<button class="message-close" @click="message = ''">×</button>
|
||||
</div>
|
||||
|
||||
<div class="tab-navigation">
|
||||
<button
|
||||
v-for="tab in tabs"
|
||||
:key="tab.id"
|
||||
@click="activeTab = tab.id"
|
||||
class="tab-button"
|
||||
:class="{ active: activeTab === tab.id }"
|
||||
@click="activeTab = tab.id"
|
||||
>
|
||||
<component :is="tab.icon" :size="18" />
|
||||
<span>{{ tab.label }}</span>
|
||||
@@ -395,17 +396,17 @@ const loadCurrentAdminPassword = async () => {
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
@click="handleSelectDataDir"
|
||||
class="input-addon-btn"
|
||||
:title="t('settings.service.network.dataDir.selectTitle')"
|
||||
@click="handleSelectDataDir"
|
||||
>
|
||||
<FolderOpen :size="16" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@click="handleOpenDataDir"
|
||||
class="input-addon-btn"
|
||||
:title="t('settings.service.network.dataDir.openTitle')"
|
||||
@click="handleOpenDataDir"
|
||||
>
|
||||
<ExternalLink :size="16" />
|
||||
</button>
|
||||
@@ -457,10 +458,10 @@ const loadCurrentAdminPassword = async () => {
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
@click="handleResetAdminPassword"
|
||||
:disabled="isResettingPassword"
|
||||
class="input-addon-btn reset-password-btn"
|
||||
:title="t('settings.service.admin.resetTitle')"
|
||||
@click="handleResetAdminPassword"
|
||||
>
|
||||
<RotateCcw :size="16" />
|
||||
</button>
|
||||
@@ -500,9 +501,9 @@ const loadCurrentAdminPassword = async () => {
|
||||
<div class="settings-section-actions">
|
||||
<button
|
||||
type="button"
|
||||
@click="handleOpenRcloneConfig"
|
||||
class="btn btn-secondary"
|
||||
:title="t('settings.rclone.config.openFile')"
|
||||
@click="handleOpenRcloneConfig"
|
||||
>
|
||||
<ExternalLink :size="16" />
|
||||
{{ t('settings.rclone.config.openFile') }}
|
||||
@@ -530,8 +531,8 @@ const loadCurrentAdminPassword = async () => {
|
||||
<label>{{ t('settings.theme.title') }}</label>
|
||||
<select
|
||||
v-model="appSettings.theme"
|
||||
@change="appStore.setTheme(appSettings.theme || 'light')"
|
||||
class="form-input"
|
||||
@change="appStore.setTheme(appSettings.theme || 'light')"
|
||||
>
|
||||
<option value="light">{{ t('settings.app.theme.light') }}</option>
|
||||
<option value="dark">{{ t('settings.app.theme.dark') }}</option>
|
||||
@@ -550,9 +551,9 @@ const loadCurrentAdminPassword = async () => {
|
||||
<div class="settings-section-actions">
|
||||
<button
|
||||
type="button"
|
||||
@click="handleOpenSettingsFile"
|
||||
class="btn btn-secondary"
|
||||
:title="t('settings.app.config.openFile')"
|
||||
@click="handleOpenSettingsFile"
|
||||
>
|
||||
<ExternalLink :size="16" />
|
||||
{{ t('settings.app.config.openFile') }}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<p class="view-subtitle">{{ t('update.subtitle') }}</p>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button @click="goToSettings" class="settings-link">
|
||||
<button class="settings-link" @click="goToSettings">
|
||||
<Settings :size="16" />
|
||||
{{ t('navigation.settings') }}
|
||||
</button>
|
||||
@@ -36,10 +36,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useTranslation } from '../composables/useI18n'
|
||||
import { Settings } from 'lucide-vue-next'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import UpdateManagerCard from '../components/dashboard/UpdateManagerCard.vue'
|
||||
import { useTranslation } from '../composables/useI18n'
|
||||
|
||||
const { t } = useTranslation()
|
||||
const router = useRouter()
|
||||
|
||||
14
src/vite-env.d.ts
vendored
14
src/vite-env.d.ts
vendored
@@ -1,12 +1,12 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
declare module "*.vue" {
|
||||
import type { DefineComponent } from "vue";
|
||||
const component: DefineComponent<{}, {}, any>;
|
||||
export default component;
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
|
||||
declare module "*.json" {
|
||||
const value: any;
|
||||
export default value;
|
||||
declare module '*.json' {
|
||||
const value: any
|
||||
export default value
|
||||
}
|
||||
|
||||
534
yarn.lock
534
yarn.lock
@@ -332,7 +332,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz#7fc114af5f6563f19f73324b5d5ff36ece0803d1"
|
||||
integrity sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==
|
||||
|
||||
"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.5.0", "@eslint-community/eslint-utils@^4.7.0":
|
||||
"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0", "@eslint-community/eslint-utils@^4.5.0", "@eslint-community/eslint-utils@^4.7.0":
|
||||
version "4.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz#607084630c6c033992a082de6e6fbc1a8b52175a"
|
||||
integrity sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==
|
||||
@@ -579,6 +579,18 @@
|
||||
resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-11.1.11.tgz#6bba3b86617c05767356e4ca939c9e300563a083"
|
||||
integrity sha512-RIBFTIqxZSsxUqlcyoR7iiC632bq7kkOwYvZlvcVObHfrF4NhuKc4FKvu8iPCrEO+e3XsY7/UVpfgzg+M7ETzA==
|
||||
|
||||
"@isaacs/cliui@^8.0.2":
|
||||
version "8.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
|
||||
integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==
|
||||
dependencies:
|
||||
string-width "^5.1.2"
|
||||
string-width-cjs "npm:string-width@^4.2.0"
|
||||
strip-ansi "^7.0.1"
|
||||
strip-ansi-cjs "npm:strip-ansi@^6.0.1"
|
||||
wrap-ansi "^8.1.0"
|
||||
wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
|
||||
|
||||
"@isaacs/fs-minipass@^4.0.0":
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32"
|
||||
@@ -612,6 +624,16 @@
|
||||
"@nodelib/fs.scandir" "2.1.5"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@pkgjs/parseargs@^0.11.0":
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
"@pkgr/core@^0.2.9":
|
||||
version "0.2.9"
|
||||
resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b"
|
||||
integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==
|
||||
|
||||
"@rolldown/pluginutils@1.0.0-beta.29":
|
||||
version "1.0.0-beta.29"
|
||||
resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.29.tgz#f8fc9a8788757dccba0d3b7fee93183621773d4c"
|
||||
@@ -742,77 +764,77 @@
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/api/-/api-2.8.0.tgz#0348a2b3ba5982ec67a7d569f329b4a55d7d5f1e"
|
||||
integrity sha512-ga7zdhbS2GXOMTIZRT0mYjKJtR9fivsXzsyq5U3vjDL0s6DTMwYRm0UHNjzTY5dh4+LSC68Sm/7WEiimbQNYlw==
|
||||
|
||||
"@tauri-apps/cli-darwin-arm64@2.8.2":
|
||||
version "2.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.8.2.tgz#aca5cf87e0fb151b6ed50fa2ff4b1e52b9561138"
|
||||
integrity sha512-tVYb17WKtbNZF4fI3NgIsZ/+7H9YWQpkNPDPpwdba1CxEik/fqg7mTm7rJLuOtDk0ukFoN53JbZaVx+wCJmTOA==
|
||||
"@tauri-apps/cli-darwin-arm64@2.8.3":
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.8.3.tgz#dc212e7a73616b637cca130846925e037bda3ec9"
|
||||
integrity sha512-+X/DjTlH9ZLT9kWrU+Mk9TSu8vVpv30GgfAOKUxlCQobaRSOzN0cxgZfRcgWaDLu80/gWsJ7Ktk9jLfJ9h9CVA==
|
||||
|
||||
"@tauri-apps/cli-darwin-x64@2.8.2":
|
||||
version "2.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.8.2.tgz#e0c2a2b0e609d167f194e0355a0024bd33a8c138"
|
||||
integrity sha512-oNsduNfxe5lYDa7bn1lmlWrnKYWEw04k8jWSZiYtt/5pyZcGUu6GjwEN6Gsoo+glR6Xl7FTb88G1VId1YOacTg==
|
||||
"@tauri-apps/cli-darwin-x64@2.8.3":
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.8.3.tgz#14292ae91d3fe48300f8255cb8dc2e413c4fddbc"
|
||||
integrity sha512-Bs+DK+gGinSj373DEeAuZMUrvTE1m7X5Ef2jC2lU2X8ZhQf4VBV+gNMRoOlSuwIlSTU2eKDQsExtKeFFSpbc8A==
|
||||
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf@2.8.2":
|
||||
version "2.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.8.2.tgz#eb03e16460699d460e32f7b970aa1066eab7b99c"
|
||||
integrity sha512-zmvkxHbK49MY39uh/AVUG/WiA/pDrBiRjHFURzFPdsircQCOQFzr0aMG3Gam7ePJlm4T7Vc7Gd8vhENfgPblnQ==
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf@2.8.3":
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.8.3.tgz#19c52c20ac3edd9c539943f426d5eecff27036e3"
|
||||
integrity sha512-9pri7KWES6x0M0DWCr5RIsGtXD4yy83Zsf8xuSmn8z6xboFquSnfJZmFsfPz25G8awLFIhxUkxP0YtZGiIUy7g==
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-gnu@2.8.2":
|
||||
version "2.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.8.2.tgz#c16124f99c7cd23010c9cc584ec004dc6004348e"
|
||||
integrity sha512-gdYmMwEUC2Rx2xC8+9diwSSWQJ5Zklju4XC248PzOt5BJz4r0TbnOC5NUmuow2+uuP9Ul2lozCW4/lu/Y6Lseg==
|
||||
"@tauri-apps/cli-linux-arm64-gnu@2.8.3":
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.8.3.tgz#fcd38eb860be151b11dd056e43a8431c3f3277bf"
|
||||
integrity sha512-2+qRdUgnFJ7pDW69dFZxYduWEZPya3U2YA6GaDhrYTHBq8/ypPSpuUT+BZ6n9r68+ij7tFMTj+vwNDgNp3M/0w==
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-musl@2.8.2":
|
||||
version "2.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.8.2.tgz#2294e8fab11c79d088bc11f1f914b774c84cd417"
|
||||
integrity sha512-AgiGwBhR9FUnTd7JT8ru2JSNBR7PST9CdZgBZfBUynuff2/vHSBI2LblEijKBmyiC68nTJhVIa4SFTtFY16TJg==
|
||||
"@tauri-apps/cli-linux-arm64-musl@2.8.3":
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.8.3.tgz#efda12db88b20cefcfcea26fb477f84bb08f7efc"
|
||||
integrity sha512-DJHW1vcqmLMqZCBiu9qv7/oYAygNC6xvrxwrUWvWMvaz/qKNy9NVXZm/EUx+sLTCcOxWHyJe+CII1kW3ouI18Q==
|
||||
|
||||
"@tauri-apps/cli-linux-riscv64-gnu@2.8.2":
|
||||
version "2.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.8.2.tgz#32b50f70b025caeb3c116dce75aa0064767f47bf"
|
||||
integrity sha512-YZ9x1mKad1s4IsjVCPRZHNoxsG+/k8bIpx6SIoQDYtWnj75P0NBStUG3D72xUjZVGsj/EqOhFJ30hW2dwSteWQ==
|
||||
"@tauri-apps/cli-linux-riscv64-gnu@2.8.3":
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.8.3.tgz#acb0e17580bad1ed3bf3cd7a049e069a31f63d6b"
|
||||
integrity sha512-+CbLaQXAqd5lPJnfXGyitbgp/q5mnsvCoToGspeVMBYNGd04ES/6XDEcXH7EwNCTgXBTJVRYf3qhI8a8/x31Aw==
|
||||
|
||||
"@tauri-apps/cli-linux-x64-gnu@2.8.2":
|
||||
version "2.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.8.2.tgz#50d7618c76979e5f62d19c764c4984aee73d3903"
|
||||
integrity sha512-Of7CR7RXqwWJcKYaCuazDgWPuWHCaHAEvL1NMGX8Ck3vdfcjReSQo/QEnf5EYtJpNdItEmIrbbYWrHI9QsNEfQ==
|
||||
"@tauri-apps/cli-linux-x64-gnu@2.8.3":
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.8.3.tgz#c680908b2d0fce5e0c7cb0fdd4206eb716e4cefc"
|
||||
integrity sha512-FGjLnA+3PTJwoN5KEMAi6Q8I6SkuW5w8qSFKldGx2Mma8GqtttXqIDw1BzxcIw/LMcr6JrxjbIRULzmV05q/QA==
|
||||
|
||||
"@tauri-apps/cli-linux-x64-musl@2.8.2":
|
||||
version "2.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.8.2.tgz#ff24a51243f78de2f4cb736c453eec7b5ba5c40f"
|
||||
integrity sha512-GBBKksPKwxpagE9SPoJtrnEMd5a5UVBEkaGsC1E0BbmiOjf2hL3rlvjEvNEzOGU1zX5XEiDvd5xbrCEdxL7r3g==
|
||||
"@tauri-apps/cli-linux-x64-musl@2.8.3":
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.8.3.tgz#4dfff284274734e68a189c068a1f69925eeaeed5"
|
||||
integrity sha512-tWRX3rQJCeUq9mR0Rc0tUV+pdgGL94UqVIzPn0/VmhDehdiDouRdXOUPggJrYUz2Aj/4RvVa83J6B8Hg37s8RQ==
|
||||
|
||||
"@tauri-apps/cli-win32-arm64-msvc@2.8.2":
|
||||
version "2.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.8.2.tgz#5f47da53c7f51653ea320ab032ad50ab0d231ea2"
|
||||
integrity sha512-1oXevTQErlyJCPwBU0JD1HNmCucSrb+ujBS5fNFAiRnmu1e9NOiJHKsg+iTvzB24oTdSYhRQLpbP0GbsWhD8hQ==
|
||||
"@tauri-apps/cli-win32-arm64-msvc@2.8.3":
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.8.3.tgz#4d11e6c4786a8d511ca022ee25182182185096c2"
|
||||
integrity sha512-UQHDmbSMIeWs/Yr3KmtfZFs5m6b+NWUe2+NE7fHu3o4EzPrvNa/Uf4U2XsYKOr0V/yetxZH0/fc+xovcnsqyqA==
|
||||
|
||||
"@tauri-apps/cli-win32-ia32-msvc@2.8.2":
|
||||
version "2.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.8.2.tgz#25cda168982682bee0078f76ba712e7c8d5e448c"
|
||||
integrity sha512-RynsG2+Kxs6JNG4i/5azFJ28OqXl7V82RUkBwTrHYXXA7bXIM/qN8wEekKmALM+aN8BJbWF38ZvJaXztvv/uKg==
|
||||
"@tauri-apps/cli-win32-ia32-msvc@2.8.3":
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.8.3.tgz#422c4449acc0b1b471c251c4fed508ec474ba34c"
|
||||
integrity sha512-aIP38i2KeADboPD1wsBFYdodEQ9PIJe0HW2urd3ocHpGxF8gX/KMiGOwGVSobu9gFlCpFNoVwCX6J1S5pJCRIQ==
|
||||
|
||||
"@tauri-apps/cli-win32-x64-msvc@2.8.2":
|
||||
version "2.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.8.2.tgz#f81b68238e1fd008008f92aea4112c2a1fb15b1f"
|
||||
integrity sha512-nVbBXQC0FIjkPmr1Fq+yqwZvVLBE2zID4Ilc9wt0JsOa6TrKaGPGFc17NZW2RA2RaLeErhlcnKFUL0tmnPIZgA==
|
||||
"@tauri-apps/cli-win32-x64-msvc@2.8.3":
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.8.3.tgz#85ad29b61db51e2a5df833da0a40c67f0825a3d6"
|
||||
integrity sha512-Z+H+PwK+3yMffG1rN7iqs+uPo6FkPyHJ4MTtFhnEvvGzc3aH711bwFb6+PXwMXfOb/jPR/LB+o6kEXghBu9ynQ==
|
||||
|
||||
"@tauri-apps/cli@^2.8.2":
|
||||
version "2.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli/-/cli-2.8.2.tgz#bc7ffbd27478d7cab7cfa46ae37703462f9671f0"
|
||||
integrity sha512-aVGBjYufTIsG10LJPbzqkWpVPJrBz03rhXhY434htJ1eHEJ67gPjJO3yUPaiLhaIUjbUeyQusgeGTWT1obV0IA==
|
||||
"@tauri-apps/cli@^2.8.3":
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/cli/-/cli-2.8.3.tgz#4d1feca61596d156b49cca2092df7fd002328b7d"
|
||||
integrity sha512-5IlcOtVBI6HYcTRFH4tuLZV+FX09Psi4Xi+TyFf/S8T8w+ZzPNnrehHz6KUGRbuXHfJhtmRDoUULXNEhpdVkfA==
|
||||
optionalDependencies:
|
||||
"@tauri-apps/cli-darwin-arm64" "2.8.2"
|
||||
"@tauri-apps/cli-darwin-x64" "2.8.2"
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf" "2.8.2"
|
||||
"@tauri-apps/cli-linux-arm64-gnu" "2.8.2"
|
||||
"@tauri-apps/cli-linux-arm64-musl" "2.8.2"
|
||||
"@tauri-apps/cli-linux-riscv64-gnu" "2.8.2"
|
||||
"@tauri-apps/cli-linux-x64-gnu" "2.8.2"
|
||||
"@tauri-apps/cli-linux-x64-musl" "2.8.2"
|
||||
"@tauri-apps/cli-win32-arm64-msvc" "2.8.2"
|
||||
"@tauri-apps/cli-win32-ia32-msvc" "2.8.2"
|
||||
"@tauri-apps/cli-win32-x64-msvc" "2.8.2"
|
||||
"@tauri-apps/cli-darwin-arm64" "2.8.3"
|
||||
"@tauri-apps/cli-darwin-x64" "2.8.3"
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf" "2.8.3"
|
||||
"@tauri-apps/cli-linux-arm64-gnu" "2.8.3"
|
||||
"@tauri-apps/cli-linux-arm64-musl" "2.8.3"
|
||||
"@tauri-apps/cli-linux-riscv64-gnu" "2.8.3"
|
||||
"@tauri-apps/cli-linux-x64-gnu" "2.8.3"
|
||||
"@tauri-apps/cli-linux-x64-musl" "2.8.3"
|
||||
"@tauri-apps/cli-win32-arm64-msvc" "2.8.3"
|
||||
"@tauri-apps/cli-win32-ia32-msvc" "2.8.3"
|
||||
"@tauri-apps/cli-win32-x64-msvc" "2.8.3"
|
||||
|
||||
"@tauri-apps/plugin-autostart@^2.5.0":
|
||||
version "2.5.0"
|
||||
@@ -849,12 +871,12 @@
|
||||
dependencies:
|
||||
"@tauri-apps/api" "^2.6.0"
|
||||
|
||||
"@tauri-apps/plugin-shell@^2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/plugin-shell/-/plugin-shell-2.3.0.tgz#b0c8d1dfbcd8ce6c72a6b366e94a3b146eaa5267"
|
||||
integrity sha512-6GIRxO2z64uxPX4CCTuhQzefvCC0ew7HjdBhMALiGw74vFBDY95VWueAHOHgNOMV4UOUAFupyidN9YulTe5xlA==
|
||||
"@tauri-apps/plugin-shell@^2.3.1":
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@tauri-apps/plugin-shell/-/plugin-shell-2.3.1.tgz#e92fb07e7bcf48ba647e5c8ef78e2ea8b469db15"
|
||||
integrity sha512-jjs2WGDO/9z2pjNlydY/F5yYhNsscv99K5lCmU5uKjsVvQ3dRlDhhtVYoa4OLDmktLtQvgvbQjCFibMl6tgGfw==
|
||||
dependencies:
|
||||
"@tauri-apps/api" "^2.6.0"
|
||||
"@tauri-apps/api" "^2.8.0"
|
||||
|
||||
"@tauri-apps/plugin-store@^2.4.0":
|
||||
version "2.4.0"
|
||||
@@ -906,30 +928,30 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901"
|
||||
integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==
|
||||
|
||||
"@typescript-eslint/eslint-plugin@8.40.0", "@typescript-eslint/eslint-plugin@^8.40.0":
|
||||
version "8.40.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz#19f959f273b32f5082c891903645e6a85328db4e"
|
||||
integrity sha512-w/EboPlBwnmOBtRbiOvzjD+wdiZdgFeo17lkltrtn7X37vagKKWJABvyfsJXTlHe6XBzugmYgd4A4nW+k8Mixw==
|
||||
"@typescript-eslint/eslint-plugin@8.41.0", "@typescript-eslint/eslint-plugin@^8.41.0":
|
||||
version "8.41.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.41.0.tgz#42209e2ce3e2274de0f5f9b75c777deedacaa558"
|
||||
integrity sha512-8fz6oa6wEKZrhXWro/S3n2eRJqlRcIa6SlDh59FXJ5Wp5XRZ8B9ixpJDcjadHq47hMx0u+HW6SNa6LjJQ6NLtw==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.10.0"
|
||||
"@typescript-eslint/scope-manager" "8.40.0"
|
||||
"@typescript-eslint/type-utils" "8.40.0"
|
||||
"@typescript-eslint/utils" "8.40.0"
|
||||
"@typescript-eslint/visitor-keys" "8.40.0"
|
||||
"@typescript-eslint/scope-manager" "8.41.0"
|
||||
"@typescript-eslint/type-utils" "8.41.0"
|
||||
"@typescript-eslint/utils" "8.41.0"
|
||||
"@typescript-eslint/visitor-keys" "8.41.0"
|
||||
graphemer "^1.4.0"
|
||||
ignore "^7.0.0"
|
||||
natural-compare "^1.4.0"
|
||||
ts-api-utils "^2.1.0"
|
||||
|
||||
"@typescript-eslint/parser@8.40.0", "@typescript-eslint/parser@^8.40.0":
|
||||
version "8.40.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.40.0.tgz#1bc9f3701ced29540eb76ff2d95ce0d52ddc7e69"
|
||||
integrity sha512-jCNyAuXx8dr5KJMkecGmZ8KI61KBUhkCob+SD+C+I5+Y1FWI2Y3QmY4/cxMCC5WAsZqoEtEETVhUiUMIGCf6Bw==
|
||||
"@typescript-eslint/parser@8.41.0", "@typescript-eslint/parser@^8.41.0":
|
||||
version "8.41.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.41.0.tgz#677f5b2b3fa947ee1eac4129220c051b1990d898"
|
||||
integrity sha512-gTtSdWX9xiMPA/7MV9STjJOOYtWwIJIYxkQxnSV1U3xcE+mnJSH3f6zI0RYP+ew66WSlZ5ed+h0VCxsvdC1jJg==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "8.40.0"
|
||||
"@typescript-eslint/types" "8.40.0"
|
||||
"@typescript-eslint/typescript-estree" "8.40.0"
|
||||
"@typescript-eslint/visitor-keys" "8.40.0"
|
||||
"@typescript-eslint/scope-manager" "8.41.0"
|
||||
"@typescript-eslint/types" "8.41.0"
|
||||
"@typescript-eslint/typescript-estree" "8.41.0"
|
||||
"@typescript-eslint/visitor-keys" "8.41.0"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/project-service@8.34.1":
|
||||
@@ -941,13 +963,13 @@
|
||||
"@typescript-eslint/types" "^8.34.1"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/project-service@8.40.0":
|
||||
version "8.40.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.40.0.tgz#1b7ba6079ff580c3215882fe75a43e5d3ed166b9"
|
||||
integrity sha512-/A89vz7Wf5DEXsGVvcGdYKbVM9F7DyFXj52lNYUDS1L9yJfqjW/fIp5PgMuEJL/KeqVTe2QSbXAGUZljDUpArw==
|
||||
"@typescript-eslint/project-service@8.41.0":
|
||||
version "8.41.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.41.0.tgz#08ebf882d413a038926e73fda36e00c3dba84882"
|
||||
integrity sha512-b8V9SdGBQzQdjJ/IO3eDifGpDBJfvrNTp2QD9P2BeqWTGrRibgfgIlBSw6z3b6R7dPzg752tOs4u/7yCLxksSQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/tsconfig-utils" "^8.40.0"
|
||||
"@typescript-eslint/types" "^8.40.0"
|
||||
"@typescript-eslint/tsconfig-utils" "^8.41.0"
|
||||
"@typescript-eslint/types" "^8.41.0"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.34.1":
|
||||
@@ -958,32 +980,32 @@
|
||||
"@typescript-eslint/types" "8.34.1"
|
||||
"@typescript-eslint/visitor-keys" "8.34.1"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.40.0":
|
||||
version "8.40.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.40.0.tgz#2fbfcc8643340d8cd692267e61548b946190be8a"
|
||||
integrity sha512-y9ObStCcdCiZKzwqsE8CcpyuVMwRouJbbSrNuThDpv16dFAj429IkM6LNb1dZ2m7hK5fHyzNcErZf7CEeKXR4w==
|
||||
"@typescript-eslint/scope-manager@8.41.0":
|
||||
version "8.41.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.41.0.tgz#c8aba12129cb9cead1f1727f58e6a0fcebeecdb5"
|
||||
integrity sha512-n6m05bXn/Cd6DZDGyrpXrELCPVaTnLdPToyhBoFkLIMznRUQUEQdSp96s/pcWSQdqOhrgR1mzJ+yItK7T+WPMQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.40.0"
|
||||
"@typescript-eslint/visitor-keys" "8.40.0"
|
||||
"@typescript-eslint/types" "8.41.0"
|
||||
"@typescript-eslint/visitor-keys" "8.41.0"
|
||||
|
||||
"@typescript-eslint/tsconfig-utils@8.34.1", "@typescript-eslint/tsconfig-utils@^8.34.1":
|
||||
version "8.34.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.1.tgz#d6abb1b1e9f1f1c83ac92051c8fbf2dbc4dc9f5e"
|
||||
integrity sha512-K4Sjdo4/xF9NEeA2khOb7Y5nY6NSXBnod87uniVYW9kHP+hNlDV8trUSFeynA2uxWam4gIWgWoygPrv9VMWrYg==
|
||||
|
||||
"@typescript-eslint/tsconfig-utils@8.40.0", "@typescript-eslint/tsconfig-utils@^8.40.0":
|
||||
version "8.40.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.40.0.tgz#8e8fdb9b988854aedd04abdde3239c4bdd2d26e4"
|
||||
integrity sha512-jtMytmUaG9d/9kqSl/W3E3xaWESo4hFDxAIHGVW/WKKtQhesnRIJSAJO6XckluuJ6KDB5woD1EiqknriCtAmcw==
|
||||
"@typescript-eslint/tsconfig-utils@8.41.0", "@typescript-eslint/tsconfig-utils@^8.41.0":
|
||||
version "8.41.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.41.0.tgz#134dee36eb16cdd78095a20bca0516d10b5dda75"
|
||||
integrity sha512-TDhxYFPUYRFxFhuU5hTIJk+auzM/wKvWgoNYOPcOf6i4ReYlOoYN8q1dV5kOTjNQNJgzWN3TUUQMtlLOcUgdUw==
|
||||
|
||||
"@typescript-eslint/type-utils@8.40.0":
|
||||
version "8.40.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.40.0.tgz#a7e4a1f0815dd0ba3e4eef945cc87193ca32c422"
|
||||
integrity sha512-eE60cK4KzAc6ZrzlJnflXdrMqOBaugeukWICO2rB0KNvwdIMaEaYiywwHMzA1qFpTxrLhN9Lp4E/00EgWcD3Ow==
|
||||
"@typescript-eslint/type-utils@8.41.0":
|
||||
version "8.41.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.41.0.tgz#68d401e38fccf239925447e97bdbd048a9891ae5"
|
||||
integrity sha512-63qt1h91vg3KsjVVonFJWjgSK7pZHSQFKH6uwqxAH9bBrsyRhO6ONoKyXxyVBzG1lJnFAJcKAcxLS54N1ee1OQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.40.0"
|
||||
"@typescript-eslint/typescript-estree" "8.40.0"
|
||||
"@typescript-eslint/utils" "8.40.0"
|
||||
"@typescript-eslint/types" "8.41.0"
|
||||
"@typescript-eslint/typescript-estree" "8.41.0"
|
||||
"@typescript-eslint/utils" "8.41.0"
|
||||
debug "^4.3.4"
|
||||
ts-api-utils "^2.1.0"
|
||||
|
||||
@@ -992,10 +1014,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.34.1.tgz#565a46a251580dae674dac5aafa8eb14b8322a35"
|
||||
integrity sha512-rjLVbmE7HR18kDsjNIZQHxmv9RZwlgzavryL5Lnj2ujIRTeXlKtILHgRNmQ3j4daw7zd+mQgy+uyt6Zo6I0IGA==
|
||||
|
||||
"@typescript-eslint/types@8.40.0", "@typescript-eslint/types@^8.40.0":
|
||||
version "8.40.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.40.0.tgz#0b580fdf643737aa5c01285314b5c6e9543846a9"
|
||||
integrity sha512-ETdbFlgbAmXHyFPwqUIYrfc12ArvpBhEVgGAxVYSwli26dn8Ko+lIo4Su9vI9ykTZdJn+vJprs/0eZU0YMAEQg==
|
||||
"@typescript-eslint/types@8.41.0", "@typescript-eslint/types@^8.41.0":
|
||||
version "8.41.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.41.0.tgz#9935afeaae65e535abcbcee95383fa649c64d16d"
|
||||
integrity sha512-9EwxsWdVqh42afLbHP90n2VdHaWU/oWgbH2P0CfcNfdKL7CuKpwMQGjwev56vWu9cSKU7FWSu6r9zck6CVfnag==
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.34.1":
|
||||
version "8.34.1"
|
||||
@@ -1013,15 +1035,15 @@
|
||||
semver "^7.6.0"
|
||||
ts-api-utils "^2.1.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.40.0":
|
||||
version "8.40.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.40.0.tgz#295149440ce7da81c790a4e14e327599a3a1e5c9"
|
||||
integrity sha512-k1z9+GJReVVOkc1WfVKs1vBrR5MIKKbdAjDTPvIK3L8De6KbFfPFt6BKpdkdk7rZS2GtC/m6yI5MYX+UsuvVYQ==
|
||||
"@typescript-eslint/typescript-estree@8.41.0":
|
||||
version "8.41.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.41.0.tgz#7c9cff8b4334ce96f14e9689692e8cf426ce4d59"
|
||||
integrity sha512-D43UwUYJmGhuwHfY7MtNKRZMmfd8+p/eNSfFe6tH5mbVDto+VQCayeAt35rOx3Cs6wxD16DQtIKw/YXxt5E0UQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/project-service" "8.40.0"
|
||||
"@typescript-eslint/tsconfig-utils" "8.40.0"
|
||||
"@typescript-eslint/types" "8.40.0"
|
||||
"@typescript-eslint/visitor-keys" "8.40.0"
|
||||
"@typescript-eslint/project-service" "8.41.0"
|
||||
"@typescript-eslint/tsconfig-utils" "8.41.0"
|
||||
"@typescript-eslint/types" "8.41.0"
|
||||
"@typescript-eslint/visitor-keys" "8.41.0"
|
||||
debug "^4.3.4"
|
||||
fast-glob "^3.3.2"
|
||||
is-glob "^4.0.3"
|
||||
@@ -1029,15 +1051,15 @@
|
||||
semver "^7.6.0"
|
||||
ts-api-utils "^2.1.0"
|
||||
|
||||
"@typescript-eslint/utils@8.40.0":
|
||||
version "8.40.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.40.0.tgz#8d0c6430ed2f5dc350784bb0d8be514da1e54054"
|
||||
integrity sha512-Cgzi2MXSZyAUOY+BFwGs17s7ad/7L+gKt6Y8rAVVWS+7o6wrjeFN4nVfTpbE25MNcxyJ+iYUXflbs2xR9h4UBg==
|
||||
"@typescript-eslint/utils@8.41.0":
|
||||
version "8.41.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.41.0.tgz#17cb3b766c1626311004ea41ffd8c27eb226b953"
|
||||
integrity sha512-udbCVstxZ5jiPIXrdH+BZWnPatjlYwJuJkDA4Tbo3WyYLh8NvB+h/bKeSZHDOFKfphsZYJQqaFtLeXEqurQn1A==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.7.0"
|
||||
"@typescript-eslint/scope-manager" "8.40.0"
|
||||
"@typescript-eslint/types" "8.40.0"
|
||||
"@typescript-eslint/typescript-estree" "8.40.0"
|
||||
"@typescript-eslint/scope-manager" "8.41.0"
|
||||
"@typescript-eslint/types" "8.41.0"
|
||||
"@typescript-eslint/typescript-estree" "8.41.0"
|
||||
|
||||
"@typescript-eslint/utils@^8.26.1":
|
||||
version "8.34.1"
|
||||
@@ -1057,12 +1079,12 @@
|
||||
"@typescript-eslint/types" "8.34.1"
|
||||
eslint-visitor-keys "^4.2.1"
|
||||
|
||||
"@typescript-eslint/visitor-keys@8.40.0":
|
||||
version "8.40.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.40.0.tgz#c1b45196981311fed7256863be4bfb2d3eda332a"
|
||||
integrity sha512-8CZ47QwalyRjsypfwnbI3hKy5gJDPmrkLjkgMxhi0+DZZ2QNx2naS6/hWoVYUHU7LU2zleF68V9miaVZvhFfTA==
|
||||
"@typescript-eslint/visitor-keys@8.41.0":
|
||||
version "8.41.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.41.0.tgz#16eb99b55d207f6688002a2cf425e039579aa9a9"
|
||||
integrity sha512-+GeGMebMCy0elMNg67LRNoVnUFPIm37iu5CmHESVx56/9Jsfdpsvbv605DQ81Pi/x11IdKUsS5nzgTYbCQU9fg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.40.0"
|
||||
"@typescript-eslint/types" "8.41.0"
|
||||
eslint-visitor-keys "^4.2.1"
|
||||
|
||||
"@vitejs/plugin-vue@^6.0.1":
|
||||
@@ -1357,7 +1379,7 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
||||
dependencies:
|
||||
color-convert "^2.0.1"
|
||||
|
||||
ansi-styles@^6.0.0, ansi-styles@^6.2.1:
|
||||
ansi-styles@^6.0.0, ansi-styles@^6.1.0, ansi-styles@^6.2.1:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
|
||||
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
|
||||
@@ -1401,6 +1423,11 @@ bl@^4.1.0:
|
||||
inherits "^2.0.4"
|
||||
readable-stream "^3.4.0"
|
||||
|
||||
boolbase@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
|
||||
integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.12"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843"
|
||||
@@ -1470,7 +1497,7 @@ chalk@^2.4.1, chalk@^2.4.2:
|
||||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1:
|
||||
chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||
@@ -1762,6 +1789,11 @@ cross-spawn@^7.0.1, cross-spawn@^7.0.6:
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
cssesc@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
||||
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
|
||||
|
||||
csstype@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
|
||||
@@ -1813,7 +1845,7 @@ de-indent@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
|
||||
integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==
|
||||
|
||||
debug@4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.1:
|
||||
debug@4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.0, debug@^4.4.1:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b"
|
||||
integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==
|
||||
@@ -1854,6 +1886,24 @@ dot-prop@^5.1.0:
|
||||
dependencies:
|
||||
is-obj "^2.0.0"
|
||||
|
||||
dpdm@^3.14.0:
|
||||
version "3.14.0"
|
||||
resolved "https://registry.yarnpkg.com/dpdm/-/dpdm-3.14.0.tgz#12a60a2d88b23981c91239b86e7462a5c203e5e9"
|
||||
integrity sha512-YJzsFSyEtj88q5eTELg3UWU7TVZkG1dpbF4JDQ3t1b07xuzXmdoGeSz9TKOke1mUuOpWlk4q+pBh+aHzD6GBTg==
|
||||
dependencies:
|
||||
chalk "^4.1.2"
|
||||
fs-extra "^11.1.1"
|
||||
glob "^10.3.4"
|
||||
ora "^5.4.1"
|
||||
tslib "^2.6.2"
|
||||
typescript "^5.2.2"
|
||||
yargs "^17.7.2"
|
||||
|
||||
eastasianwidth@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
|
||||
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
|
||||
|
||||
editor@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/editor/-/editor-1.0.0.tgz#60c7f87bd62bcc6a894fa8ccd6afb7823a24f742"
|
||||
@@ -1874,6 +1924,11 @@ emoji-regex@^8.0.0:
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
||||
|
||||
emoji-regex@^9.2.2:
|
||||
version "9.2.2"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
|
||||
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
|
||||
|
||||
enhanced-resolve@^5.17.1:
|
||||
version "5.18.1"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz#728ab082f8b7b6836de51f1637aab5d3b9568faf"
|
||||
@@ -1957,6 +2012,11 @@ eslint-compat-utils@^0.5.1:
|
||||
dependencies:
|
||||
semver "^7.5.4"
|
||||
|
||||
eslint-config-prettier@^10.1.8:
|
||||
version "10.1.8"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz#15734ce4af8c2778cc32f0b01b37b0b5cd1ecb97"
|
||||
integrity sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==
|
||||
|
||||
eslint-plugin-es-x@^7.8.0:
|
||||
version "7.8.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz#a207aa08da37a7923f2a9599e6d3eb73f3f92b74"
|
||||
@@ -1982,6 +2042,14 @@ eslint-plugin-n@^17.20.0:
|
||||
semver "^7.6.3"
|
||||
ts-declaration-location "^1.0.6"
|
||||
|
||||
eslint-plugin-prettier@^5.5.4:
|
||||
version "5.5.4"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz#9d61c4ea11de5af704d4edf108c82ccfa7f2e61c"
|
||||
integrity sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==
|
||||
dependencies:
|
||||
prettier-linter-helpers "^1.0.0"
|
||||
synckit "^0.11.7"
|
||||
|
||||
eslint-plugin-simple-import-sort@^12.1.1:
|
||||
version "12.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.1.tgz#e64bfdaf91c5b98a298619aa634a9f7aa43b709e"
|
||||
@@ -2011,7 +2079,19 @@ eslint-plugin-unicorn@^60.0.0:
|
||||
semver "^7.7.2"
|
||||
strip-indent "^4.0.0"
|
||||
|
||||
eslint-scope@^8.4.0:
|
||||
eslint-plugin-vue@^10.4.0:
|
||||
version "10.4.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-10.4.0.tgz#2ae20df43801d20515c58ec2ae0555bf1127a080"
|
||||
integrity sha512-K6tP0dW8FJVZLQxa2S7LcE1lLw3X8VvB3t887Q6CLrFVxHYBXGANbXvwNzYIu6Ughx1bSJ5BDT0YB3ybPT39lw==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.4.0"
|
||||
natural-compare "^1.4.0"
|
||||
nth-check "^2.1.1"
|
||||
postcss-selector-parser "^6.0.15"
|
||||
semver "^7.6.3"
|
||||
xml-name-validator "^4.0.0"
|
||||
|
||||
eslint-scope@^8.2.0, eslint-scope@^8.4.0:
|
||||
version "8.4.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82"
|
||||
integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==
|
||||
@@ -2024,7 +2104,7 @@ eslint-visitor-keys@^3.4.3:
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint-visitor-keys@^4.2.1:
|
||||
eslint-visitor-keys@^4.2.0, eslint-visitor-keys@^4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1"
|
||||
integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==
|
||||
@@ -2070,7 +2150,7 @@ eslint@^9.34.0:
|
||||
natural-compare "^1.4.0"
|
||||
optionator "^0.9.3"
|
||||
|
||||
espree@^10.0.1, espree@^10.4.0:
|
||||
espree@^10.0.1, espree@^10.3.0, espree@^10.4.0:
|
||||
version "10.4.0"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837"
|
||||
integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==
|
||||
@@ -2134,6 +2214,11 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||
|
||||
fast-diff@^1.1.2:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0"
|
||||
integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==
|
||||
|
||||
fast-glob@^3.3.2:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818"
|
||||
@@ -2285,6 +2370,14 @@ flatted@^3.2.9:
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358"
|
||||
integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==
|
||||
|
||||
foreground-child@^3.1.0:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f"
|
||||
integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==
|
||||
dependencies:
|
||||
cross-spawn "^7.0.6"
|
||||
signal-exit "^4.0.1"
|
||||
|
||||
formdata-polyfill@^4.0.10:
|
||||
version "4.0.10"
|
||||
resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
|
||||
@@ -2302,7 +2395,7 @@ fs-extra@9.1.0:
|
||||
jsonfile "^6.0.1"
|
||||
universalify "^2.0.0"
|
||||
|
||||
fs-extra@^11.3.1:
|
||||
fs-extra@^11.1.1, fs-extra@^11.3.1:
|
||||
version "11.3.1"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.1.tgz#ba7a1f97a85f94c6db2e52ff69570db3671d5a74"
|
||||
integrity sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==
|
||||
@@ -2373,6 +2466,18 @@ glob@7.2.3, glob@^7.1.3:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^10.3.4:
|
||||
version "10.4.5"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956"
|
||||
integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==
|
||||
dependencies:
|
||||
foreground-child "^3.1.0"
|
||||
jackspeak "^3.1.2"
|
||||
minimatch "^9.0.4"
|
||||
minipass "^7.1.2"
|
||||
package-json-from-dist "^1.0.0"
|
||||
path-scurry "^1.11.1"
|
||||
|
||||
global-directory@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/global-directory/-/global-directory-4.0.1.tgz#4d7ac7cfd2cb73f304c53b8810891748df5e361e"
|
||||
@@ -2713,6 +2818,15 @@ isexe@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
|
||||
|
||||
jackspeak@^3.1.2:
|
||||
version "3.4.3"
|
||||
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a"
|
||||
integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==
|
||||
dependencies:
|
||||
"@isaacs/cliui" "^8.0.2"
|
||||
optionalDependencies:
|
||||
"@pkgjs/parseargs" "^0.11.0"
|
||||
|
||||
jiti@^2.4.1:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.2.tgz#d19b7732ebb6116b06e2038da74a55366faef560"
|
||||
@@ -2933,15 +3047,15 @@ longest@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/longest/-/longest-2.0.1.tgz#781e183296aa94f6d4d916dc335d0d17aefa23f8"
|
||||
integrity sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==
|
||||
|
||||
lru-cache@^10.0.1:
|
||||
lru-cache@^10.0.1, lru-cache@^10.2.0:
|
||||
version "10.4.3"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
|
||||
integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
|
||||
|
||||
lucide-vue-next@^0.541.0:
|
||||
version "0.541.0"
|
||||
resolved "https://registry.yarnpkg.com/lucide-vue-next/-/lucide-vue-next-0.541.0.tgz#3096a4dbbb2615364b3f0fcba83a18ad7fcb7d0d"
|
||||
integrity sha512-BXY//i7H0ojCDRmux7WzhTl2FiKVmE42fyaLuQOKBGaeBRLEGkkSgYMBxIk9ZjAKa+JELRmFVV1xAFUumB89QA==
|
||||
lucide-vue-next@^0.542.0:
|
||||
version "0.542.0"
|
||||
resolved "https://registry.yarnpkg.com/lucide-vue-next/-/lucide-vue-next-0.542.0.tgz#ff5287edc8da8043b716b0b91833de2fee9fc65e"
|
||||
integrity sha512-cJfyhFoneDgYTouHwUJEutXaCW5EQuRrBsvfELudWnMiwfqvcEtpZTFZLdZ5Nrqow+znzn+Iyhu3KeYIfa3mEg==
|
||||
|
||||
magic-string@^0.30.17:
|
||||
version "0.30.17"
|
||||
@@ -3022,7 +3136,7 @@ minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8:
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
||||
|
||||
minipass@^7.0.4, minipass@^7.1.2:
|
||||
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4, minipass@^7.1.2:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707"
|
||||
integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==
|
||||
@@ -3142,6 +3256,13 @@ normalize-package-data@^7.0.0:
|
||||
semver "^7.3.5"
|
||||
validate-npm-package-license "^3.0.4"
|
||||
|
||||
nth-check@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
|
||||
integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==
|
||||
dependencies:
|
||||
boolbase "^1.0.0"
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
@@ -3250,6 +3371,11 @@ p-locate@^6.0.0:
|
||||
dependencies:
|
||||
p-limit "^4.0.0"
|
||||
|
||||
package-json-from-dist@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505"
|
||||
integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==
|
||||
|
||||
parent-module@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
|
||||
@@ -3297,6 +3423,14 @@ path-key@^3.1.0:
|
||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
|
||||
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
||||
|
||||
path-scurry@^1.11.1:
|
||||
version "1.11.1"
|
||||
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2"
|
||||
integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==
|
||||
dependencies:
|
||||
lru-cache "^10.2.0"
|
||||
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||
|
||||
perfect-debounce@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz#9c2e8bc30b169cc984a58b7d5b28049839591d2a"
|
||||
@@ -3339,6 +3473,14 @@ pluralize@^8.0.0:
|
||||
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
|
||||
integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
|
||||
|
||||
postcss-selector-parser@^6.0.15:
|
||||
version "6.1.2"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz#27ecb41fb0e3b6ba7a1ec84fff347f734c7929de"
|
||||
integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==
|
||||
dependencies:
|
||||
cssesc "^3.0.0"
|
||||
util-deprecate "^1.0.2"
|
||||
|
||||
postcss@^8.5.6:
|
||||
version "8.5.6"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c"
|
||||
@@ -3353,6 +3495,18 @@ prelude-ls@^1.2.1:
|
||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
||||
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
|
||||
|
||||
prettier-linter-helpers@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
|
||||
integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
|
||||
dependencies:
|
||||
fast-diff "^1.1.2"
|
||||
|
||||
prettier@^3.6.2:
|
||||
version "3.6.2"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.6.2.tgz#ccda02a1003ebbb2bfda6f83a074978f608b9393"
|
||||
integrity sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
|
||||
@@ -3550,7 +3704,7 @@ signal-exit@^3.0.2:
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
||||
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
||||
|
||||
signal-exit@^4.1.0:
|
||||
signal-exit@^4.0.1, signal-exit@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
|
||||
integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
|
||||
@@ -3627,6 +3781,15 @@ string-argv@^0.3.2:
|
||||
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6"
|
||||
integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==
|
||||
|
||||
"string-width-cjs@npm:string-width@^4.2.0":
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
dependencies:
|
||||
emoji-regex "^8.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
string-width@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
|
||||
@@ -3644,6 +3807,15 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
string-width@^5.0.1, string-width@^5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
|
||||
integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
|
||||
dependencies:
|
||||
eastasianwidth "^0.2.0"
|
||||
emoji-regex "^9.2.2"
|
||||
strip-ansi "^7.0.1"
|
||||
|
||||
string-width@^7.0.0, string-width@^7.2.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc"
|
||||
@@ -3660,6 +3832,13 @@ string_decoder@^1.1.1:
|
||||
dependencies:
|
||||
safe-buffer "~5.2.0"
|
||||
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-ansi@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
|
||||
@@ -3681,7 +3860,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-ansi@^7.1.0:
|
||||
strip-ansi@^7.0.1, strip-ansi@^7.1.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
|
||||
integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==
|
||||
@@ -3726,6 +3905,13 @@ supports-color@^7.1.0:
|
||||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
synckit@^0.11.7:
|
||||
version "0.11.11"
|
||||
resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.11.tgz#c0b619cf258a97faa209155d9cd1699b5c998cb0"
|
||||
integrity sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==
|
||||
dependencies:
|
||||
"@pkgr/core" "^0.2.9"
|
||||
|
||||
tapable@^2.2.0:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.2.tgz#ab4984340d30cb9989a490032f086dbb8b56d872"
|
||||
@@ -3805,7 +3991,7 @@ tslib@^1.9.0:
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2.1.0:
|
||||
tslib@^2.1.0, tslib@^2.6.2:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
|
||||
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
|
||||
@@ -3822,15 +4008,20 @@ type-fest@^0.21.3:
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
|
||||
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
|
||||
|
||||
typescript-eslint@^8.40.0:
|
||||
version "8.40.0"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.40.0.tgz#27541748f3ca889c9698327bdacf815f7dc61804"
|
||||
integrity sha512-Xvd2l+ZmFDPEt4oj1QEXzA4A2uUK6opvKu3eGN9aGjB8au02lIVcLyi375w94hHyejTOmzIU77L8ol2sRg9n7Q==
|
||||
typescript-eslint@^8.41.0:
|
||||
version "8.41.0"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.41.0.tgz#a13879a5998717140fefb0d808c8c2fbde1cb769"
|
||||
integrity sha512-n66rzs5OBXW3SFSnZHr2T685q1i4ODm2nulFJhMZBotaTavsS8TrI3d7bDlRSs9yWo7HmyWrN9qDu14Qv7Y0Dw==
|
||||
dependencies:
|
||||
"@typescript-eslint/eslint-plugin" "8.40.0"
|
||||
"@typescript-eslint/parser" "8.40.0"
|
||||
"@typescript-eslint/typescript-estree" "8.40.0"
|
||||
"@typescript-eslint/utils" "8.40.0"
|
||||
"@typescript-eslint/eslint-plugin" "8.41.0"
|
||||
"@typescript-eslint/parser" "8.41.0"
|
||||
"@typescript-eslint/typescript-estree" "8.41.0"
|
||||
"@typescript-eslint/utils" "8.41.0"
|
||||
|
||||
typescript@^5.2.2:
|
||||
version "5.9.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.2.tgz#d93450cddec5154a2d5cabe3b8102b83316fb2a6"
|
||||
integrity sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==
|
||||
|
||||
typescript@^5.8.3:
|
||||
version "5.8.3"
|
||||
@@ -3889,7 +4080,7 @@ user-home@^2.0.0:
|
||||
dependencies:
|
||||
os-homedir "^1.0.0"
|
||||
|
||||
util-deprecate@^1.0.1:
|
||||
util-deprecate@^1.0.1, util-deprecate@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||
@@ -3921,6 +4112,18 @@ vscode-uri@^3.0.8:
|
||||
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.1.0.tgz#dd09ec5a66a38b5c3fffc774015713496d14e09c"
|
||||
integrity sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==
|
||||
|
||||
vue-eslint-parser@^10.2.0:
|
||||
version "10.2.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-10.2.0.tgz#cb53f89b14c7f5bf6a95c9532e3b2961ab619d61"
|
||||
integrity sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==
|
||||
dependencies:
|
||||
debug "^4.4.0"
|
||||
eslint-scope "^8.2.0"
|
||||
eslint-visitor-keys "^4.2.0"
|
||||
espree "^10.3.0"
|
||||
esquery "^1.6.0"
|
||||
semver "^7.6.3"
|
||||
|
||||
vue-i18n@11.1.11:
|
||||
version "11.1.11"
|
||||
resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-11.1.11.tgz#b38ed214896540cf7a68932dfa565d9d4fbbffac"
|
||||
@@ -3997,6 +4200,15 @@ wordwrap@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
|
||||
integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==
|
||||
|
||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrap-ansi@^6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
|
||||
@@ -4015,6 +4227,15 @@ wrap-ansi@^7.0.0:
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrap-ansi@^8.1.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
|
||||
integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
|
||||
dependencies:
|
||||
ansi-styles "^6.1.0"
|
||||
string-width "^5.0.1"
|
||||
strip-ansi "^7.0.1"
|
||||
|
||||
wrap-ansi@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.0.tgz#1a3dc8b70d85eeb8398ddfb1e4a02cd186e58b3e"
|
||||
@@ -4029,6 +4250,11 @@ wrappy@1:
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
|
||||
|
||||
xml-name-validator@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835"
|
||||
integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==
|
||||
|
||||
y18n@^5.0.5:
|
||||
version "5.0.8"
|
||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
||||
@@ -4049,7 +4275,7 @@ yargs-parser@^21.1.1:
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
|
||||
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
|
||||
|
||||
yargs@^17.0.0:
|
||||
yargs@^17.0.0, yargs@^17.7.2:
|
||||
version "17.7.2"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
|
||||
integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
|
||||
|
||||
Reference in New Issue
Block a user