diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 74bc06bf..be91d5c6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,326 +1,376 @@ name: Build and Release on: - push: - branches: - - main - - dev - paths: - - 'src/**' - - 'src-tauri/**' - - '**.json' - - '**.toml' - - '**.yml' - - '**.yaml' - - workflow_dispatch: + push: + branches: + - main + - dev + paths: + - "src/**" + - "src-tauri/**" + - "**.json" + - "**.toml" + - "**.yml" + - "**.yaml" + + workflow_dispatch: jobs: - check-skip: - runs-on: ubuntu-latest - outputs: - skip: ${{ steps.check.outputs.skip }} - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Check commit messages for skip keywords - id: check - shell: bash - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - set -euo pipefail - - keywords='\[skip ci\]|\[ci skip\]|skip-ci|skip_ci|SKIP_CI|NO_CI|skipci' - - # Determine the single relevant commit SHA: - # - For pull_request events use the PR head SHA - # - Otherwise prefer .after, head_commit.id, or GITHUB_SHA - commit_sha="$(jq -r '.pull_request.head.sha // .after // .head_commit.id // .sha // empty' < "$GITHUB_EVENT_PATH" 2>/dev/null || true)" - commit_sha="${commit_sha:-${GITHUB_SHA:-}}" - - if [ -z "$commit_sha" ]; then - echo "No commit SHA found; defaulting to full log fallback." - messages="$(git log --pretty=%B -n 10 || true)" - else - echo "Checking commit: $commit_sha" - # try to fetch the specific SHA if it's not present locally - if ! git cat-file -e "$commit_sha^{commit}" 2>/dev/null; then - git fetch --no-tags --depth=1 origin "$commit_sha" || git fetch --no-tags --depth=50 origin +refs/heads/*:refs/remotes/origin/* || true - fi - messages="$(git show -s --format=%B "$commit_sha" 2>/dev/null || true)" - fi - - # Fallback: if no message found, try event commits array - if [ -z "$(echo "$messages" | tr -d '[:space:]')" ]; then - messages="$(jq -r '.commits[]?.message // empty' < "$GITHUB_EVENT_PATH" 2>/dev/null || true)" - fi - - echo "---- Collected commit message(s) ----" - if [ -n "$(echo "$messages" | tr -d '[:space:]')" ]; then - printf "%s\n" "$messages" - else - echo "" - fi - echo "---- End commit message(s) ----" - - echo "---- Matching lines (case-insensitive) ----" - echo "$messages" | nl -ba | grep -Ei --color=never "$keywords" || true - echo "---- End matching lines ----" - - skip_found=false - if echo "$messages" | grep -Ei "$keywords" >/dev/null; then - echo "Found skip keyword in commit message. Cancelling run." - skip_found=true - else - echo "No skip keyword found in commit message. Continuing run." - fi - - echo "skip=$skip_found" >> $GITHUB_OUTPUT - - build: - needs: check-skip - if: needs.check-skip.outputs.skip != 'true' - strategy: - fail-fast: false - matrix: - platform: [windows-latest, ubuntu-latest] - - runs-on: ${{ matrix.platform }} - permissions: - contents: write - actions: write - id-token: write - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - - - name: Install Rust stable - uses: dtolnay/rust-toolchain@stable - - - name: Setup sccache - uses: mozilla-actions/sccache-action@v0.0.9 - - - name: Cache sccache - uses: actions/cache@v4 - with: - path: | - ~/.cache/sccache - ~/AppData/Local/Mozilla/sccache - key: ${{ runner.os }}-sccache-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-sccache- - - - name: Install dependencies (ubuntu only) - if: matrix.platform == 'ubuntu-latest' - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev libappindicator3-dev librsvg2-dev patchelf \ - build-essential curl wget file libssl-dev \ - libjavascriptcoregtk-4.1-dev libwebkit2gtk-4.1-dev \ - libsoup-3.0-dev pkg-config - - - name: Configure pkg-config (Ubuntu only) - if: matrix.platform == 'ubuntu-latest' - run: | - echo "PKG_CONFIG_PATH=/usr/lib/pkgconfig:/usr/share/pkgconfig:/usr/lib/x86_64-linux-gnu/pkgconfig" >> $GITHUB_ENV - ls -la /usr/lib/x86_64-linux-gnu/pkgconfig/ || true - pkg-config --list-all | grep -i javascript || true - - - name: Install frontend dependencies (Windows) - if: matrix.platform == 'windows-latest' - run: npm ci; npm install - - - name: Install frontend dependencies (Ubuntu) - if: matrix.platform == 'ubuntu-latest' - run: npm ci || npm install - - - name: Get version from package.json (Ubuntu) - if: matrix.platform == 'ubuntu-latest' - id: package-version-ubuntu - uses: martinbeentjes/npm-get-version-action@main - - - name: Get version from package.json (Windows) - if: matrix.platform == 'windows-latest' - id: package-version-windows - shell: bash - run: echo "current-version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT - - - name: Get commit hash - id: commit-hash - run: echo "HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - shell: bash - - - name: Build the app - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - RUSTC_WRAPPER: sccache - PKG_CONFIG_PATH: /usr/lib/pkgconfig:/usr/share/pkgconfig - PKG_CONFIG_ALLOW_SYSTEM_CFLAGS: 1 - PKG_CONFIG_ALLOW_SYSTEM_LIBS: 1 - with: - includeUpdaterJson: true - updaterJsonKeepUniversal: true - - - name: Show sccache stats - run: sccache --show-stats - - - name: Collect Windows artifacts - if: matrix.platform == 'windows-latest' - shell: pwsh - run: | - mkdir -p artifacts-windows - $version = "${{ steps.package-version-windows.outputs.current-version }}" - - Get-ChildItem -Path ./src-tauri/target/release/bundle/msi/*.msi -Recurse | ForEach-Object { - Copy-Item $_.FullName -Destination artifacts-windows/ - $md5 = Get-FileHash $_.FullName -Algorithm MD5 - echo "MSI_MD5=$($md5.Hash)" >> $env:GITHUB_ENV - } - - Get-ChildItem -Path ./src-tauri/target/release/bundle/nsis/*-setup.exe -Recurse | ForEach-Object { - Copy-Item $_.FullName -Destination artifacts-windows/ - $md5 = Get-FileHash $_.FullName -Algorithm MD5 - echo "NSIS_MD5=$($md5.Hash)" >> $env:GITHUB_ENV - } - - Get-ChildItem -Path ./src-tauri/target/release/*.exe | ForEach-Object { - $baseName = [System.IO.Path]::GetFileNameWithoutExtension($_.Name) - $extension = [System.IO.Path]::GetExtension($_.Name) - $newName = "${baseName}_${version}${extension}" - $newPath = Join-Path "artifacts-windows" $newName - Copy-Item $_.FullName -Destination $newPath - $md5 = Get-FileHash $_.FullName -Algorithm MD5 - echo "EXE_MD5=$($md5.Hash)" >> $env:GITHUB_ENV - } - - echo "ARTIFACT_PATH=artifacts-windows" >> $env:GITHUB_ENV - - - name: Collect Ubuntu artifacts - if: matrix.platform == 'ubuntu-latest' - run: | - mkdir -p artifacts-ubuntu - version="${{ steps.package-version-ubuntu.outputs.current-version }}" - - find ./src-tauri/target/release/bundle/deb -name "*.deb" | while read file; do - cp "$file" artifacts-ubuntu/ - MD5=$(md5sum "$file" | awk '{ print $1 }') - echo "DEB_MD5=$MD5" >> $GITHUB_ENV - done - - find ./src-tauri/target/release/bundle/appimage -name "*.AppImage" 2>/dev/null | while read file; do - cp "$file" artifacts-ubuntu/ - MD5=$(md5sum "$file" | awk '{ print $1 }') - echo "APPIMAGE_MD5=$MD5" >> $GITHUB_ENV - done - - # Include the standalone Linux binary with version - find ./src-tauri/target/release -maxdepth 1 -type f -executable -not -name "*.so" -not -name "*.d" | while read file; do - if [ -f "$file" ] && file "$file" | grep -q "ELF.*executable"; then - basename=$(basename "$file") - extension="" - if [[ "$basename" == *.* ]]; then - extension=".${basename##*.}" - basename="${basename%.*}" - fi - versioned_name="${basename}_${version}${extension}" - cp "$file" "artifacts-ubuntu/$versioned_name" - MD5=$(md5sum "$file" | awk '{ print $1 }') - echo "BINARY_MD5=$MD5" >> $GITHUB_ENV - fi - done - - echo "ARTIFACT_PATH=artifacts-ubuntu" >> $GITHUB_ENV - - - name: VirusTotal Scan (Windows only) - if: matrix.platform == 'windows-latest' && github.event.repository.fork == false - uses: crazy-max/ghaction-virustotal@v4 - id: virustotal - with: - vt_api_key: ${{ secrets.VT_API_KEY }} - files: | - artifacts-windows/*.msi - artifacts-windows/*-setup.exe - artifacts-windows/*.exe - - - name: Extract and Print URL(s) of VirusTotal Scan (Windows only) - if: matrix.platform == 'windows-latest' && github.event.repository.fork == false && steps.virustotal.outputs.analysis != '' - shell: bash - run: | - ANALYSIS="${{ steps.virustotal.outputs.analysis }}" - urls=$(echo "$ANALYSIS" | tr ',' '\n' | grep -oE 'https?://[^[:space:]]*virustotal[^[:space:]]*' | sed 's/[[:space:]]*$//' | uniq) - if [ -n "$urls" ]; then - printf 'VIRUSTOTAL_URL<> $GITHUB_ENV - printf 'VIRUSTOTAL_LINE<> $GITHUB_ENV - else - echo "VIRUSTOTAL_URL=" >> $GITHUB_ENV - echo "VIRUSTOTAL_LINE=" >> $GITHUB_ENV - fi - - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: CollapseLoader-${{ matrix.platform }}-${{ env.HASH }} - path: ${{ matrix.platform == 'windows-latest' && 'artifacts-windows/**' || 'artifacts-ubuntu/**' }} - - create-release: - needs: [check-skip, build] - if: needs.check-skip.outputs.skip != 'true' - runs-on: ubuntu-latest - permissions: - contents: write - actions: read - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - - - name: Get version from package.json - id: package-version - run: echo "current-version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT - - - name: Get commit hash - id: commit-hash - run: echo "HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - shell: bash - - - name: Download all artifacts - uses: actions/download-artifact@v4 - with: - path: release-artifacts - - - name: List artifacts - run: find release-artifacts -type f - - - name: Create Release - uses: softprops/action-gh-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - VIRUSTOTAL_LINE: ${{ env.VIRUSTOTAL_LINE }} - with: - tag_name: prerelease-v${{ steps.package-version.outputs.current-version }}-${{ env.HASH }} - name: 'CollapseLoader ${{ steps.package-version.outputs.current-version }}-${{ env.HASH }}' - body: | - - Automatic build from GitHub Actions - - - Windows (.msi, .exe installer, standalone .exe with version) - - Linux (.deb, standalone binary with version) - - Note: This is an automated build from the main branch. - Commit hash: ${{ env.HASH }} - ${{ env.VIRUSTOTAL_LINE }} - files: release-artifacts/**/* - prerelease: true + check-skip: + runs-on: ubuntu-latest + outputs: + skip: ${{ steps.check.outputs.skip }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Check commit messages for skip keywords + id: check + shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + + keywords='\[skip ci\]|\[ci skip\]|skip-ci|skip_ci|SKIP_CI|NO_CI|skipci' + + # Determine the single relevant commit SHA: + # - For pull_request events use the PR head SHA + # - Otherwise prefer .after, head_commit.id, or GITHUB_SHA + commit_sha="$(jq -r '.pull_request.head.sha // .after // .head_commit.id // .sha // empty' < "$GITHUB_EVENT_PATH" 2>/dev/null || true)" + commit_sha="${commit_sha:-${GITHUB_SHA:-}}" + + if [ -z "$commit_sha" ]; then + echo "No commit SHA found; defaulting to full log fallback." + messages="$(git log --pretty=%B -n 10 || true)" + else + echo "Checking commit: $commit_sha" + # try to fetch the specific SHA if it's not present locally + if ! git cat-file -e "$commit_sha^{commit}" 2>/dev/null; then + git fetch --no-tags --depth=1 origin "$commit_sha" || git fetch --no-tags --depth=50 origin +refs/heads/*:refs/remotes/origin/* || true + fi + messages="$(git show -s --format=%B "$commit_sha" 2>/dev/null || true)" + fi + + # Fallback: if no message found, try event commits array + if [ -z "$(echo "$messages" | tr -d '[:space:]')" ]; then + messages="$(jq -r '.commits[]?.message // empty' < "$GITHUB_EVENT_PATH" 2>/dev/null || true)" + fi + + echo "---- Collected commit message(s) ----" + if [ -n "$(echo "$messages" | tr -d '[:space:]')" ]; then + printf "%s\n" "$messages" + else + echo "" + fi + echo "---- End commit message(s) ----" + + echo "---- Matching lines (case-insensitive) ----" + echo "$messages" | nl -ba | grep -Ei --color=never "$keywords" || true + echo "---- End matching lines ----" + + skip_found=false + if echo "$messages" | grep -Ei "$keywords" >/dev/null; then + echo "Found skip keyword in commit message. Cancelling run." + skip_found=true + else + echo "No skip keyword found in commit message. Continuing run." + fi + + echo "skip=$skip_found" >> $GITHUB_OUTPUT + + build: + needs: check-skip + if: needs.check-skip.outputs.skip != 'true' + strategy: + fail-fast: false + matrix: + platform: [windows-latest, ubuntu-latest] + + runs-on: ${{ matrix.platform }} + permissions: + contents: write + actions: write + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: Setup sccache + uses: mozilla-actions/sccache-action@v0.0.9 + + - name: Cache sccache + uses: actions/cache@v4 + with: + path: | + ~/.cache/sccache + ~/AppData/Local/Mozilla/sccache + key: ${{ runner.os }}-sccache-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-sccache- + + - name: Install dependencies (ubuntu only) + if: matrix.platform == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y libgtk-3-dev libappindicator3-dev librsvg2-dev patchelf \ + build-essential curl wget file libssl-dev \ + libjavascriptcoregtk-4.1-dev libwebkit2gtk-4.1-dev \ + libsoup-3.0-dev pkg-config + + - name: Configure pkg-config (Ubuntu only) + if: matrix.platform == 'ubuntu-latest' + run: | + echo "PKG_CONFIG_PATH=/usr/lib/pkgconfig:/usr/share/pkgconfig:/usr/lib/x86_64-linux-gnu/pkgconfig" >> $GITHUB_ENV + ls -la /usr/lib/x86_64-linux-gnu/pkgconfig/ || true + pkg-config --list-all | grep -i javascript || true + + - name: Install frontend dependencies (Windows) + if: matrix.platform == 'windows-latest' + run: npm ci; npm install + + - name: Install frontend dependencies (Ubuntu) + if: matrix.platform == 'ubuntu-latest' + run: npm ci || npm install + + - name: Get version from package.json (Ubuntu) + if: matrix.platform == 'ubuntu-latest' + id: package-version-ubuntu + uses: martinbeentjes/npm-get-version-action@main + + - name: Get version from package.json (Windows) + if: matrix.platform == 'windows-latest' + id: package-version-windows + shell: bash + run: echo "current-version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT + + - name: Get commit hash + id: commit-hash + run: echo "HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV + shell: bash + + - name: Build the app + uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + RUSTC_WRAPPER: sccache + PKG_CONFIG_PATH: /usr/lib/pkgconfig:/usr/share/pkgconfig + PKG_CONFIG_ALLOW_SYSTEM_CFLAGS: 1 + PKG_CONFIG_ALLOW_SYSTEM_LIBS: 1 + with: + includeUpdaterJson: true + updaterJsonKeepUniversal: true + + - name: Show sccache stats + run: sccache --show-stats + + - name: Collect Windows artifacts + if: matrix.platform == 'windows-latest' + shell: pwsh + run: | + mkdir -p artifacts-windows + $version = "${{ steps.package-version-windows.outputs.current-version }}" + + Get-ChildItem -Path ./src-tauri/target/release/bundle/msi/*.msi -Recurse | ForEach-Object { + Copy-Item $_.FullName -Destination artifacts-windows/ + $md5 = Get-FileHash $_.FullName -Algorithm MD5 + echo "MSI_MD5=$($md5.Hash)" >> $env:GITHUB_ENV + } + + Get-ChildItem -Path ./src-tauri/target/release/bundle/nsis/*-setup.exe -Recurse | ForEach-Object { + Copy-Item $_.FullName -Destination artifacts-windows/ + $md5 = Get-FileHash $_.FullName -Algorithm MD5 + echo "NSIS_MD5=$($md5.Hash)" >> $env:GITHUB_ENV + } + + Get-ChildItem -Path ./src-tauri/target/release/*.exe | ForEach-Object { + $baseName = [System.IO.Path]::GetFileNameWithoutExtension($_.Name) + $extension = [System.IO.Path]::GetExtension($_.Name) + $newName = "${baseName}_${version}${extension}" + $newPath = Join-Path "artifacts-windows" $newName + Copy-Item $_.FullName -Destination $newPath + $md5 = Get-FileHash $_.FullName -Algorithm MD5 + echo "EXE_MD5=$($md5.Hash)" >> $env:GITHUB_ENV + } + + echo "ARTIFACT_PATH=artifacts-windows" >> $env:GITHUB_ENV + - name: Upload Windows artifacts to Telegram + if: matrix.platform == 'windows-latest' + shell: pwsh + env: + TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }} + TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHANNEL_ID }} + run: | + $token = $env:TELEGRAM_TOKEN + $chatId = $env:TELEGRAM_CHAT_ID + if (-not $token -or -not $chatId) { Write-Host "Telegram token or chat id not set; skipping upload."; exit 0 } + + $files = Get-ChildItem -Path artifacts-windows -File -Recurse | Where-Object { $_.Extension -in '.msi','.exe' -or $_.Name -like '*-setup.exe' } | ForEach-Object { $_.FullName } + if (-not $files) { Write-Host "No artifacts found to upload."; exit 0 } + + $repo = $env:GITHUB_REPOSITORY + $hash = $env:HASH + $commitUrl = "https://github.com/$repo/commit/$hash" + + # Try to get the commit subject (short message) + $commitSubject = '' + try { $commitSubject = (git log -1 --pretty=format:'%s' $hash) } catch { } + if (-not $commitSubject) { try { $commitSubject = (git log -1 --pretty=format:'%s') } catch { $commitSubject = '' } } + if (-not $commitSubject) { $commitSubject = "(no commit message)" } + + $media = @() + for ($i = 0; $i -lt $files.Count; $i++) { + $attachName = "file$i" + $item = @{ type = 'document'; media = "attach://$attachName" } + if ($i -eq 0) { + $item.caption = "Build artifacts for commit [$hash]($commitUrl) - $commitSubject" + $item.parse_mode = 'Markdown' + } + $media += $item + } + + $mediaJson = ($media | ConvertTo-Json -Compress) + $uri = "https://api.telegram.org/bot$token/sendMediaGroup" + + $form = @() + $form += '-F'; $form += "chat_id=$chatId" + $form += '-F'; $form += "media=$mediaJson" + + for ($i = 0; $i -lt $files.Count; $i++) { + $attachName = "file$i" + $path = $files[$i] + $form += '-F'; $form += "${attachName}=@$path" + } + + Write-Host "Uploading artifacts as a single media group to Telegram..." + & curl.exe -s -X POST $uri @form + + - name: Collect Ubuntu artifacts + if: matrix.platform == 'ubuntu-latest' + run: | + mkdir -p artifacts-ubuntu + version="${{ steps.package-version-ubuntu.outputs.current-version }}" + + find ./src-tauri/target/release/bundle/deb -name "*.deb" | while read file; do + cp "$file" artifacts-ubuntu/ + MD5=$(md5sum "$file" | awk '{ print $1 }') + echo "DEB_MD5=$MD5" >> $GITHUB_ENV + done + + find ./src-tauri/target/release/bundle/appimage -name "*.AppImage" 2>/dev/null | while read file; do + cp "$file" artifacts-ubuntu/ + MD5=$(md5sum "$file" | awk '{ print $1 }') + echo "APPIMAGE_MD5=$MD5" >> $GITHUB_ENV + done + + # Include the standalone Linux binary with version + find ./src-tauri/target/release -maxdepth 1 -type f -executable -not -name "*.so" -not -name "*.d" | while read file; do + if [ -f "$file" ] && file "$file" | grep -q "ELF.*executable"; then + basename=$(basename "$file") + extension="" + if [[ "$basename" == *.* ]]; then + extension=".${basename##*.}" + basename="${basename%.*}" + fi + versioned_name="${basename}_${version}${extension}" + cp "$file" "artifacts-ubuntu/$versioned_name" + MD5=$(md5sum "$file" | awk '{ print $1 }') + echo "BINARY_MD5=$MD5" >> $GITHUB_ENV + fi + done + + echo "ARTIFACT_PATH=artifacts-ubuntu" >> $GITHUB_ENV + + - name: VirusTotal Scan (Windows only) + if: matrix.platform == 'windows-latest' && github.event.repository.fork == false + uses: crazy-max/ghaction-virustotal@v4 + id: virustotal + with: + vt_api_key: ${{ secrets.VT_API_KEY }} + files: | + artifacts-windows/*.msi + artifacts-windows/*-setup.exe + artifacts-windows/*.exe + + - name: Extract and Print URL(s) of VirusTotal Scan (Windows only) + if: matrix.platform == 'windows-latest' && github.event.repository.fork == false && steps.virustotal.outputs.analysis != '' + shell: bash + run: | + ANALYSIS="${{ steps.virustotal.outputs.analysis }}" + urls=$(echo "$ANALYSIS" | tr ',' '\n' | grep -oE 'https?://[^[:space:]]*virustotal[^[:space:]]*' | sed 's/[[:space:]]*$//' | uniq) + if [ -n "$urls" ]; then + printf 'VIRUSTOTAL_URL<> $GITHUB_ENV + printf 'VIRUSTOTAL_LINE<> $GITHUB_ENV + else + echo "VIRUSTOTAL_URL=" >> $GITHUB_ENV + echo "VIRUSTOTAL_LINE=" >> $GITHUB_ENV + fi + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: CollapseLoader-${{ matrix.platform }}-${{ env.HASH }} + path: ${{ matrix.platform == 'windows-latest' && 'artifacts-windows/**' || 'artifacts-ubuntu/**' }} + + create-release: + needs: [check-skip, build] + if: needs.check-skip.outputs.skip != 'true' + runs-on: ubuntu-latest + permissions: + contents: write + actions: read + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Get version from package.json + id: package-version + run: echo "current-version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT + + - name: Get commit hash + id: commit-hash + run: echo "HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV + shell: bash + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: release-artifacts + + - name: List artifacts + run: find release-artifacts -type f + + - name: Create Release + uses: softprops/action-gh-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VIRUSTOTAL_LINE: ${{ env.VIRUSTOTAL_LINE }} + with: + tag_name: prerelease-v${{ steps.package-version.outputs.current-version }}-${{ env.HASH }} + name: "CollapseLoader ${{ steps.package-version.outputs.current-version }}-${{ env.HASH }}" + body: | + + Automatic build from GitHub Actions + + - Windows (.msi, .exe installer, standalone .exe with version) + - Linux (.deb, standalone binary with version) + + Note: This is an automated build from the main branch. + Commit hash: ${{ env.HASH }} + ${{ env.VIRUSTOTAL_LINE }} + files: release-artifacts/**/* + prerelease: true diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 00000000..763af247 --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,2 @@ +trailingComma: 'es5' +tabWidth: 4 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 965c75ab..85959885 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,42 +1,43 @@ { "name": "collapseloader", - "version": "0.2.7", + "version": "0.2.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "collapseloader", - "version": "0.2.7", + "version": "0.2.8", "dependencies": { "@guolao/vue-monaco-editor": "1.6.0", - "@sentry/vue": "^10.36.0", - "@tauri-apps/api": "2.9.1", + "@stomp/stompjs": "^7.3.0", + "@tauri-apps/api": "2.10.1", "@tauri-apps/plugin-dialog": "2.6.0", "@tauri-apps/plugin-fs": "2.4.5", "@tauri-apps/plugin-notification": "2.3.3", "@tauri-apps/plugin-opener": "2.5.3", - "axios": "1.13.2", - "daisyui": "5.5.14", + "axios": "1.13.5", + "daisyui": "5.5.19", "gsap": "3.14.2", - "lucide-vue-next": "0.562.0", + "lucide-vue-next": "0.575.0", "monaco-editor": "^0.55.1", - "vue": "3.5.27", - "vue-i18n": "11.2.8", - "vue3-lottie": "3.3.1" + "vue": "3.5.28", + "vue-i18n": "11.2.8" }, "devDependencies": { - "@tailwindcss/vite": "4.1.18", - "@tauri-apps/cli": "2.9.6", - "@types/node": "25.0.10", - "@typescript-eslint/eslint-plugin": "8.53.1", - "@typescript-eslint/parser": "8.53.1", - "@vitejs/plugin-vue": "6.0.3", - "eslint": "9.39.2", - "eslint-plugin-vue": "10.7.0", - "tailwindcss": "4.1.18", + "@tailwindcss/vite": "4.2.0", + "@tauri-apps/cli": "2.10.0", + "@types/node": "25.3.0", + "@typescript-eslint/eslint-plugin": "8.56.0", + "@typescript-eslint/parser": "8.56.0", + "@vitejs/plugin-vue": "6.0.4", + "eslint": "^10.0.1", + "eslint-plugin-vue": "10.8.0", + "prettier": "3.8.1", + "tailwindcss": "4.2.0", "typescript": "5.9.3", "vite": "7.3.1", - "vue-tsc": "3.2.2" + "vue-eslint-parser": "^10.4.0", + "vue-tsc": "3.2.5" } }, "node_modules/@babel/helper-string-parser": { @@ -58,12 +59,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", - "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", "license": "MIT", "dependencies": { - "@babel/types": "^7.28.6" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -73,9 +74,9 @@ } }, "node_modules/@babel/types": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", - "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -86,9 +87,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", "cpu": [ "ppc64" ], @@ -103,9 +104,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", "cpu": [ "arm" ], @@ -120,9 +121,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", "cpu": [ "arm64" ], @@ -137,9 +138,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", "cpu": [ "x64" ], @@ -154,9 +155,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", "cpu": [ "arm64" ], @@ -171,9 +172,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", "cpu": [ "x64" ], @@ -188,9 +189,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", "cpu": [ "arm64" ], @@ -205,9 +206,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", "cpu": [ "x64" ], @@ -222,9 +223,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", "cpu": [ "arm" ], @@ -239,9 +240,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", "cpu": [ "arm64" ], @@ -256,9 +257,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", "cpu": [ "ia32" ], @@ -273,9 +274,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", "cpu": [ "loong64" ], @@ -290,9 +291,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", "cpu": [ "mips64el" ], @@ -307,9 +308,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", "cpu": [ "ppc64" ], @@ -324,9 +325,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", "cpu": [ "riscv64" ], @@ -341,9 +342,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", "cpu": [ "s390x" ], @@ -358,9 +359,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", "cpu": [ "x64" ], @@ -375,9 +376,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", "cpu": [ "arm64" ], @@ -392,9 +393,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", "cpu": [ "x64" ], @@ -409,9 +410,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", "cpu": [ "arm64" ], @@ -426,9 +427,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", "cpu": [ "x64" ], @@ -443,9 +444,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", "cpu": [ "arm64" ], @@ -460,9 +461,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", "cpu": [ "x64" ], @@ -477,9 +478,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", "cpu": [ "arm64" ], @@ -494,9 +495,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", "cpu": [ "ia32" ], @@ -511,9 +512,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", "cpu": [ "x64" ], @@ -557,163 +558,107 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.2.tgz", + "integrity": "sha512-YF+fE6LV4v5MGWRGj7G404/OZzGNepVF8fxk7jqmqo3lrza7a0uUcDnROGRBG1WFC1omYUS/Wp1f42i0M+3Q3A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.7", + "@eslint/object-schema": "^3.0.2", "debug": "^4.3.1", - "minimatch": "^3.1.2" + "minimatch": "^10.2.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/@eslint/config-array/node_modules/balanced-match": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", + "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.17.0" - }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "20 || >=22" } }, - "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", + "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.15" + "balanced-match": "^4.0.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "20 || >=22" } }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", + "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.1", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "brace-expansion": "^5.0.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "18 || 20 || >=22" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/@eslint/config-helpers": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.2.tgz", + "integrity": "sha512-a5MxrdDXEvqnIq+LisyCX6tQMPF/dSJpCfBgBauY+pNZ28yCtSsTvyTYrMhaI+LK26bVyCJfJkT0u8KIj2i1dQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", + "@eslint/core": "^1.1.0" + }, "engines": { - "node": ">= 4" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@eslint/core": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.0.tgz", + "integrity": "sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw==", "dev": true, - "license": "ISC", + "license": "Apache-2.0", "dependencies": { - "brace-expansion": "^1.1.7" + "@types/json-schema": "^7.0.15" }, "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", - "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.2.tgz", + "integrity": "sha512-HOy56KJt48Bx8KmJ+XGQNSUMT/6dZee/M54XyUyuvTvPXJmsERRvBchsUVx1UMe1WwIH49XLAczNC7V2INsuUw==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", - "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.0.tgz", + "integrity": "sha512-bIZEUzOI1jkhviX2cp5vNyXQc6olzb2ohewQubuYlMXZ2Q/XjBO0x0XhGPvc9fjSIiUN0vw+0hq53BJ4eQSJKQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.17.0", + "@eslint/core": "^1.1.0", "levn": "^0.4.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@guolao/vue-monaco-editor": { @@ -858,6 +803,16 @@ "url": "https://github.com/sponsors/kazupon" } }, + "node_modules/@isaacs/cliui": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", + "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -917,16 +872,16 @@ } }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.53", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz", - "integrity": "sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==", + "version": "1.0.0-rc.2", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.2.tgz", + "integrity": "sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==", "dev": true, "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.56.0.tgz", - "integrity": "sha512-LNKIPA5k8PF1+jAFomGe3qN3bbIgJe/IlpDBwuVjrDKrJhVWywgnJvflMt/zkbVNLFtF1+94SljYQS6e99klnw==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", + "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", "cpu": [ "arm" ], @@ -938,9 +893,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.56.0.tgz", - "integrity": "sha512-lfbVUbelYqXlYiU/HApNMJzT1E87UPGvzveGg2h0ktUNlOCxKlWuJ9jtfvs1sKHdwU4fzY7Pl8sAl49/XaEk6Q==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", + "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", "cpu": [ "arm64" ], @@ -952,9 +907,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.56.0.tgz", - "integrity": "sha512-EgxD1ocWfhoD6xSOeEEwyE7tDvwTgZc8Bss7wCWe+uc7wO8G34HHCUH+Q6cHqJubxIAnQzAsyUsClt0yFLu06w==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", + "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", "cpu": [ "arm64" ], @@ -966,9 +921,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.56.0.tgz", - "integrity": "sha512-1vXe1vcMOssb/hOF8iv52A7feWW2xnu+c8BV4t1F//m9QVLTfNVpEdja5ia762j/UEJe2Z1jAmEqZAK42tVW3g==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", + "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", "cpu": [ "x64" ], @@ -980,9 +935,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.56.0.tgz", - "integrity": "sha512-bof7fbIlvqsyv/DtaXSck4VYQ9lPtoWNFCB/JY4snlFuJREXfZnm+Ej6yaCHfQvofJDXLDMTVxWscVSuQvVWUQ==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", + "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", "cpu": [ "arm64" ], @@ -994,9 +949,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.56.0.tgz", - "integrity": "sha512-KNa6lYHloW+7lTEkYGa37fpvPq+NKG/EHKM8+G/g9WDU7ls4sMqbVRV78J6LdNuVaeeK5WB9/9VAFbKxcbXKYg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", + "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", "cpu": [ "x64" ], @@ -1008,9 +963,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.56.0.tgz", - "integrity": "sha512-E8jKK87uOvLrrLN28jnAAAChNq5LeCd2mGgZF+fGF5D507WlG/Noct3lP/QzQ6MrqJ5BCKNwI9ipADB6jyiq2A==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", + "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", "cpu": [ "arm" ], @@ -1022,9 +977,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.56.0.tgz", - "integrity": "sha512-jQosa5FMYF5Z6prEpTCCmzCXz6eKr/tCBssSmQGEeozA9tkRUty/5Vx06ibaOP9RCrW1Pvb8yp3gvZhHwTDsJw==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", + "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", "cpu": [ "arm" ], @@ -1036,9 +991,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.56.0.tgz", - "integrity": "sha512-uQVoKkrC1KGEV6udrdVahASIsaF8h7iLG0U0W+Xn14ucFwi6uS539PsAr24IEF9/FoDtzMeeJXJIBo5RkbNWvQ==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", + "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", "cpu": [ "arm64" ], @@ -1050,9 +1005,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.56.0.tgz", - "integrity": "sha512-vLZ1yJKLxhQLFKTs42RwTwa6zkGln+bnXc8ueFGMYmBTLfNu58sl5/eXyxRa2RarTkJbXl8TKPgfS6V5ijNqEA==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", + "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", "cpu": [ "arm64" ], @@ -1064,9 +1019,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.56.0.tgz", - "integrity": "sha512-FWfHOCub564kSE3xJQLLIC/hbKqHSVxy8vY75/YHHzWvbJL7aYJkdgwD/xGfUlL5UV2SB7otapLrcCj2xnF1dg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", + "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", "cpu": [ "loong64" ], @@ -1078,9 +1033,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.56.0.tgz", - "integrity": "sha512-z1EkujxIh7nbrKL1lmIpqFTc/sr0u8Uk0zK/qIEFldbt6EDKWFk/pxFq3gYj4Bjn3aa9eEhYRlL3H8ZbPT1xvA==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", + "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", "cpu": [ "loong64" ], @@ -1092,9 +1047,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.56.0.tgz", - "integrity": "sha512-iNFTluqgdoQC7AIE8Q34R3AuPrJGJirj5wMUErxj22deOcY7XwZRaqYmB6ZKFHoVGqRcRd0mqO+845jAibKCkw==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", + "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", "cpu": [ "ppc64" ], @@ -1106,9 +1061,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.56.0.tgz", - "integrity": "sha512-MtMeFVlD2LIKjp2sE2xM2slq3Zxf9zwVuw0jemsxvh1QOpHSsSzfNOTH9uYW9i1MXFxUSMmLpeVeUzoNOKBaWg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", + "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", "cpu": [ "ppc64" ], @@ -1120,9 +1075,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.56.0.tgz", - "integrity": "sha512-in+v6wiHdzzVhYKXIk5U74dEZHdKN9KH0Q4ANHOTvyXPG41bajYRsy7a8TPKbYPl34hU7PP7hMVHRvv/5aCSew==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", + "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", "cpu": [ "riscv64" ], @@ -1134,9 +1089,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.56.0.tgz", - "integrity": "sha512-yni2raKHB8m9NQpI9fPVwN754mn6dHQSbDTwxdr9SE0ks38DTjLMMBjrwvB5+mXrX+C0npX0CVeCUcvvvD8CNQ==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", + "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", "cpu": [ "riscv64" ], @@ -1148,9 +1103,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.56.0.tgz", - "integrity": "sha512-zhLLJx9nQPu7wezbxt2ut+CI4YlXi68ndEve16tPc/iwoylWS9B3FxpLS2PkmfYgDQtosah07Mj9E0khc3Y+vQ==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", + "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", "cpu": [ "s390x" ], @@ -1162,9 +1117,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.56.0.tgz", - "integrity": "sha512-MVC6UDp16ZSH7x4rtuJPAEoE1RwS8N4oK9DLHy3FTEdFoUTCFVzMfJl/BVJ330C+hx8FfprA5Wqx4FhZXkj2Kw==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", + "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", "cpu": [ "x64" ], @@ -1176,9 +1131,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.56.0.tgz", - "integrity": "sha512-ZhGH1eA4Qv0lxaV00azCIS1ChedK0V32952Md3FtnxSqZTBTd6tgil4nZT5cU8B+SIw3PFYkvyR4FKo2oyZIHA==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", + "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", "cpu": [ "x64" ], @@ -1190,9 +1145,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.56.0.tgz", - "integrity": "sha512-O16XcmyDeFI9879pEcmtWvD/2nyxR9mF7Gs44lf1vGGx8Vg2DRNx11aVXBEqOQhWb92WN4z7fW/q4+2NYzCbBA==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", + "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", "cpu": [ "x64" ], @@ -1204,9 +1159,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.56.0.tgz", - "integrity": "sha512-LhN/Reh+7F3RCgQIRbgw8ZMwUwyqJM+8pXNT6IIJAqm2IdKkzpCh/V9EdgOMBKuebIrzswqy4ATlrDgiOwbRcQ==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", + "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", "cpu": [ "arm64" ], @@ -1218,9 +1173,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.56.0.tgz", - "integrity": "sha512-kbFsOObXp3LBULg1d3JIUQMa9Kv4UitDmpS+k0tinPBz3watcUiV2/LUDMMucA6pZO3WGE27P7DsfaN54l9ing==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", + "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", "cpu": [ "arm64" ], @@ -1232,9 +1187,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.56.0.tgz", - "integrity": "sha512-vSSgny54D6P4vf2izbtFm/TcWYedw7f8eBrOiGGecyHyQB9q4Kqentjaj8hToe+995nob/Wv48pDqL5a62EWtg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", + "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", "cpu": [ "ia32" ], @@ -1246,9 +1201,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.56.0.tgz", - "integrity": "sha512-FeCnkPCTHQJFbiGG49KjV5YGW/8b9rrXAM2Mz2kiIoktq2qsJxRD5giEMEOD2lPdgs72upzefaUvS+nc8E3UzQ==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", + "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", "cpu": [ "x64" ], @@ -1260,9 +1215,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.56.0.tgz", - "integrity": "sha512-H8AE9Ur/t0+1VXujj90w0HrSOuv0Nq9r1vSZF2t5km20NTfosQsGGUXDaKdQZzwuLts7IyL1fYT4hM95TI9c4g==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", + "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", "cpu": [ "x64" ], @@ -1273,151 +1228,56 @@ "win32" ] }, - "node_modules/@sentry-internal/browser-utils": { - "version": "10.36.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.36.0.tgz", - "integrity": "sha512-WILVR8HQBWOxbqLRuTxjzRCMIACGsDTo6jXvzA8rz6ezElElLmIrn3CFAswrESLqEEUa4CQHl5bLgSVJCRNweA==", - "license": "MIT", - "dependencies": { - "@sentry/core": "10.36.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry-internal/feedback": { - "version": "10.36.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.36.0.tgz", - "integrity": "sha512-zPjz7AbcxEyx8AHj8xvp28fYtPTPWU1XcNtymhAHJLS9CXOblqSC7W02Jxz6eo3eR1/pLyOo6kJBUjvLe9EoFA==", - "license": "MIT", - "dependencies": { - "@sentry/core": "10.36.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry-internal/replay": { - "version": "10.36.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.36.0.tgz", - "integrity": "sha512-nLMkJgvHq+uCCrQKV2KgSdVHxTsmDk0r2hsAoTcKCbzUpXyW5UhCziMRS6ULjBlzt5sbxoIIplE25ZpmIEeNgg==", - "license": "MIT", - "dependencies": { - "@sentry-internal/browser-utils": "10.36.0", - "@sentry/core": "10.36.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry-internal/replay-canvas": { - "version": "10.36.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.36.0.tgz", - "integrity": "sha512-DLGIwmT2LX+O6TyYPtOQL5GiTm2rN0taJPDJ/Lzg2KEJZrdd5sKkzTckhh2x+vr4JQyeaLmnb8M40Ch1hvG/vQ==", - "license": "MIT", - "dependencies": { - "@sentry-internal/replay": "10.36.0", - "@sentry/core": "10.36.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry/browser": { - "version": "10.36.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.36.0.tgz", - "integrity": "sha512-yHhXbgdGY1s+m8CdILC9U/II7gb6+s99S2Eh8VneEn/JG9wHc+UOzrQCeFN0phFP51QbLkjkiQbbanjT1HP8UQ==", - "license": "MIT", - "dependencies": { - "@sentry-internal/browser-utils": "10.36.0", - "@sentry-internal/feedback": "10.36.0", - "@sentry-internal/replay": "10.36.0", - "@sentry-internal/replay-canvas": "10.36.0", - "@sentry/core": "10.36.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry/core": { - "version": "10.36.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.36.0.tgz", - "integrity": "sha512-EYJjZvofI+D93eUsPLDIUV0zQocYqiBRyXS6CCV6dHz64P/Hob5NJQOwPa8/v6nD+UvJXvwsFfvXOHhYZhZJOQ==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry/vue": { - "version": "10.36.0", - "resolved": "https://registry.npmjs.org/@sentry/vue/-/vue-10.36.0.tgz", - "integrity": "sha512-pGED21QngK1ulqGsNn1NyBKgay8Cf7qZBnaxQXvnm9RaIlTGYdqg7TeooQru45We/8f0DzM6n59YykAsUu21kw==", - "license": "MIT", - "dependencies": { - "@sentry/browser": "10.36.0", - "@sentry/core": "10.36.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@tanstack/vue-router": "^1.64.0", - "pinia": "2.x || 3.x", - "vue": "2.x || 3.x" - }, - "peerDependenciesMeta": { - "@tanstack/vue-router": { - "optional": true - }, - "pinia": { - "optional": true - } - } + "node_modules/@stomp/stompjs": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@stomp/stompjs/-/stompjs-7.3.0.tgz", + "integrity": "sha512-nKMLoFfJhrQAqkvvKd1vLq/cVBGCMwPRCD0LqW7UT1fecRx9C3GoKEIR2CYwVuErGeZu8w0kFkl2rlhPlqHVgQ==", + "license": "Apache-2.0" }, "node_modules/@tailwindcss/node": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", - "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.0.tgz", + "integrity": "sha512-Yv+fn/o2OmL5fh/Ir62VXItdShnUxfpkMA4Y7jdeC8O81WPB8Kf6TT6GSHvnqgSwDzlB5iT7kDpeXxLsUS0T6Q==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/remapping": "^2.3.4", - "enhanced-resolve": "^5.18.3", + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", - "lightningcss": "1.30.2", + "lightningcss": "1.31.1", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", - "tailwindcss": "4.1.18" + "tailwindcss": "4.2.0" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz", - "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.0.tgz", + "integrity": "sha512-AZqQzADaj742oqn2xjl5JbIOzZB/DGCYF/7bpvhA8KvjUj9HJkag6bBuwZvH1ps6dfgxNHyuJVlzSr2VpMgdTQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 10" + "node": ">= 20" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.18", - "@tailwindcss/oxide-darwin-arm64": "4.1.18", - "@tailwindcss/oxide-darwin-x64": "4.1.18", - "@tailwindcss/oxide-freebsd-x64": "4.1.18", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", - "@tailwindcss/oxide-linux-x64-musl": "4.1.18", - "@tailwindcss/oxide-wasm32-wasi": "4.1.18", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" + "@tailwindcss/oxide-android-arm64": "4.2.0", + "@tailwindcss/oxide-darwin-arm64": "4.2.0", + "@tailwindcss/oxide-darwin-x64": "4.2.0", + "@tailwindcss/oxide-freebsd-x64": "4.2.0", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.0", + "@tailwindcss/oxide-linux-arm64-gnu": "4.2.0", + "@tailwindcss/oxide-linux-arm64-musl": "4.2.0", + "@tailwindcss/oxide-linux-x64-gnu": "4.2.0", + "@tailwindcss/oxide-linux-x64-musl": "4.2.0", + "@tailwindcss/oxide-wasm32-wasi": "4.2.0", + "@tailwindcss/oxide-win32-arm64-msvc": "4.2.0", + "@tailwindcss/oxide-win32-x64-msvc": "4.2.0" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz", - "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.0.tgz", + "integrity": "sha512-F0QkHAVaW/JNBWl4CEKWdZ9PMb0khw5DCELAOnu+RtjAfx5Zgw+gqCHFvqg3AirU1IAd181fwOtJQ5I8Yx5wtw==", "cpu": [ "arm64" ], @@ -1428,13 +1288,13 @@ "android" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz", - "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.0.tgz", + "integrity": "sha512-I0QylkXsBsJMZ4nkUNSR04p6+UptjcwhcVo3Zu828ikiEqHjVmQL9RuQ6uT/cVIiKpvtVA25msu/eRV97JeNSA==", "cpu": [ "arm64" ], @@ -1445,13 +1305,13 @@ "darwin" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz", - "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.0.tgz", + "integrity": "sha512-6TmQIn4p09PBrmnkvbYQ0wbZhLtbaksCDx7Y7R3FYYx0yxNA7xg5KP7dowmQ3d2JVdabIHvs3Hx4K3d5uCf8xg==", "cpu": [ "x64" ], @@ -1462,13 +1322,13 @@ "darwin" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz", - "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.0.tgz", + "integrity": "sha512-qBudxDvAa2QwGlq9y7VIzhTvp2mLJ6nD/G8/tI70DCDoneaUeLWBJaPcbfzqRIWraj+o969aDQKvKW9dvkUizw==", "cpu": [ "x64" ], @@ -1479,13 +1339,13 @@ "freebsd" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz", - "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.0.tgz", + "integrity": "sha512-7XKkitpy5NIjFZNUQPeUyNJNJn1CJeV7rmMR+exHfTuOsg8rxIO9eNV5TSEnqRcaOK77zQpsyUkBWmPy8FgdSg==", "cpu": [ "arm" ], @@ -1496,13 +1356,13 @@ "linux" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz", - "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.0.tgz", + "integrity": "sha512-Mff5a5Q3WoQR01pGU1gr29hHM1N93xYrKkGXfPw/aRtK4bOc331Ho4Tgfsm5WDGvpevqMpdlkCojT3qlCQbCpA==", "cpu": [ "arm64" ], @@ -1513,13 +1373,13 @@ "linux" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz", - "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.0.tgz", + "integrity": "sha512-XKcSStleEVnbH6W/9DHzZv1YhjE4eSS6zOu2eRtYAIh7aV4o3vIBs+t/B15xlqoxt6ef/0uiqJVB6hkHjWD/0A==", "cpu": [ "arm64" ], @@ -1530,13 +1390,13 @@ "linux" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz", - "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.0.tgz", + "integrity": "sha512-/hlXCBqn9K6fi7eAM0RsobHwJYa5V/xzWspVTzxnX+Ft9v6n+30Pz8+RxCn7sQL/vRHHLS30iQPrHQunu6/vJA==", "cpu": [ "x64" ], @@ -1547,13 +1407,13 @@ "linux" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz", - "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.0.tgz", + "integrity": "sha512-lKUaygq4G7sWkhQbfdRRBkaq4LY39IriqBQ+Gk6l5nKq6Ay2M2ZZb1tlIyRNgZKS8cbErTwuYSor0IIULC0SHw==", "cpu": [ "x64" ], @@ -1564,13 +1424,13 @@ "linux" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz", - "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.0.tgz", + "integrity": "sha512-xuDjhAsFdUuFP5W9Ze4k/o4AskUtI8bcAGU4puTYprr89QaYFmhYOPfP+d1pH+k9ets6RoE23BXZM1X1jJqoyw==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -1586,21 +1446,21 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1", + "@emnapi/core": "^1.8.1", + "@emnapi/runtime": "^1.8.1", "@emnapi/wasi-threads": "^1.1.0", - "@napi-rs/wasm-runtime": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.1.1", "@tybys/wasm-util": "^0.10.1", - "tslib": "^2.4.0" + "tslib": "^2.8.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz", - "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.0.tgz", + "integrity": "sha512-2UU/15y1sWDEDNJXxEIrfWKC2Yb4YgIW5Xz2fKFqGzFWfoMHWFlfa1EJlGO2Xzjkq/tvSarh9ZTjvbxqWvLLXA==", "cpu": [ "arm64" ], @@ -1611,13 +1471,13 @@ "win32" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz", - "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.0.tgz", + "integrity": "sha512-CrFadmFoc+z76EV6LPG1jx6XceDsaCG3lFhyLNo/bV9ByPrE+FnBPckXQVP4XRkN76h3Fjt/a+5Er/oA/nCBvQ==", "cpu": [ "x64" ], @@ -1628,28 +1488,28 @@ "win32" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/vite": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.18.tgz", - "integrity": "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.0.tgz", + "integrity": "sha512-da9mFCaHpoOgtQiWtDGIikTrSpUFBtIZCG3jy/u2BGV+l/X1/pbxzmIUxNt6JWm19N3WtGi4KlJdSH/Si83WOA==", "dev": true, "license": "MIT", "dependencies": { - "@tailwindcss/node": "4.1.18", - "@tailwindcss/oxide": "4.1.18", - "tailwindcss": "4.1.18" + "@tailwindcss/node": "4.2.0", + "@tailwindcss/oxide": "4.2.0", + "tailwindcss": "4.2.0" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "node_modules/@tauri-apps/api": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.9.1.tgz", - "integrity": "sha512-IGlhP6EivjXHepbBic618GOmiWe4URJiIeZFlB7x3czM0yDHHYviH1Xvoiv4FefdkQtn6v7TuwWCRfOGdnVUGw==", + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.10.1.tgz", + "integrity": "sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==", "license": "Apache-2.0 OR MIT", "funding": { "type": "opencollective", @@ -1657,9 +1517,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.9.6.tgz", - "integrity": "sha512-3xDdXL5omQ3sPfBfdC8fCtDKcnyV7OqyzQgfyT5P3+zY6lcPqIYKQBvUasNvppi21RSdfhy44ttvJmftb0PCDw==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.10.0.tgz", + "integrity": "sha512-ZwT0T+7bw4+DPCSWzmviwq5XbXlM0cNoleDKOYPFYqcZqeKY31KlpoMW/MOON/tOFBPgi31a2v3w9gliqwL2+Q==", "dev": true, "license": "Apache-2.0 OR MIT", "bin": { @@ -1673,23 +1533,23 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "2.9.6", - "@tauri-apps/cli-darwin-x64": "2.9.6", - "@tauri-apps/cli-linux-arm-gnueabihf": "2.9.6", - "@tauri-apps/cli-linux-arm64-gnu": "2.9.6", - "@tauri-apps/cli-linux-arm64-musl": "2.9.6", - "@tauri-apps/cli-linux-riscv64-gnu": "2.9.6", - "@tauri-apps/cli-linux-x64-gnu": "2.9.6", - "@tauri-apps/cli-linux-x64-musl": "2.9.6", - "@tauri-apps/cli-win32-arm64-msvc": "2.9.6", - "@tauri-apps/cli-win32-ia32-msvc": "2.9.6", - "@tauri-apps/cli-win32-x64-msvc": "2.9.6" + "@tauri-apps/cli-darwin-arm64": "2.10.0", + "@tauri-apps/cli-darwin-x64": "2.10.0", + "@tauri-apps/cli-linux-arm-gnueabihf": "2.10.0", + "@tauri-apps/cli-linux-arm64-gnu": "2.10.0", + "@tauri-apps/cli-linux-arm64-musl": "2.10.0", + "@tauri-apps/cli-linux-riscv64-gnu": "2.10.0", + "@tauri-apps/cli-linux-x64-gnu": "2.10.0", + "@tauri-apps/cli-linux-x64-musl": "2.10.0", + "@tauri-apps/cli-win32-arm64-msvc": "2.10.0", + "@tauri-apps/cli-win32-ia32-msvc": "2.10.0", + "@tauri-apps/cli-win32-x64-msvc": "2.10.0" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.9.6.tgz", - "integrity": "sha512-gf5no6N9FCk1qMrti4lfwP77JHP5haASZgVbBgpZG7BUepB3fhiLCXGUK8LvuOjP36HivXewjg72LTnPDScnQQ==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.10.0.tgz", + "integrity": "sha512-avqHD4HRjrMamE/7R/kzJPcAJnZs0IIS+1nkDP5b+TNBn3py7N2aIo9LIpy+VQq0AkN8G5dDpZtOOBkmWt/zjA==", "cpu": [ "arm64" ], @@ -1704,9 +1564,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.9.6.tgz", - "integrity": "sha512-oWh74WmqbERwwrwcueJyY6HYhgCksUc6NT7WKeXyrlY/FPmNgdyQAgcLuTSkhRFuQ6zh4Np1HZpOqCTpeZBDcw==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.10.0.tgz", + "integrity": "sha512-keDmlvJRStzVFjZTd0xYkBONLtgBC9eMTpmXnBXzsHuawV2q9PvDo2x6D5mhuoMVrJ9QWjgaPKBBCFks4dK71Q==", "cpu": [ "x64" ], @@ -1721,9 +1581,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.9.6.tgz", - "integrity": "sha512-/zde3bFroFsNXOHN204DC2qUxAcAanUjVXXSdEGmhwMUZeAQalNj5cz2Qli2elsRjKN/hVbZOJj0gQ5zaYUjSg==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.10.0.tgz", + "integrity": "sha512-e5u0VfLZsMAC9iHaOEANumgl6lfnJx0Dtjkd8IJpysZ8jp0tJ6wrIkto2OzQgzcYyRCKgX72aKE0PFgZputA8g==", "cpu": [ "arm" ], @@ -1738,9 +1598,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.9.6.tgz", - "integrity": "sha512-pvbljdhp9VOo4RnID5ywSxgBs7qiylTPlK56cTk7InR3kYSTJKYMqv/4Q/4rGo/mG8cVppesKIeBMH42fw6wjg==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.10.0.tgz", + "integrity": "sha512-YrYYk2dfmBs5m+OIMCrb+JH/oo+4FtlpcrTCgiFYc7vcs6m3QDd1TTyWu0u01ewsCtK2kOdluhr/zKku+KP7HA==", "cpu": [ "arm64" ], @@ -1755,9 +1615,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.9.6.tgz", - "integrity": "sha512-02TKUndpodXBCR0oP//6dZWGYcc22Upf2eP27NvC6z0DIqvkBBFziQUcvi2n6SrwTRL0yGgQjkm9K5NIn8s6jw==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.10.0.tgz", + "integrity": "sha512-GUoPdVJmrJRIXFfW3Rkt+eGK9ygOdyISACZfC/bCSfOnGt8kNdQIQr5WRH9QUaTVFIwxMlQyV3m+yXYP+xhSVA==", "cpu": [ "arm64" ], @@ -1772,9 +1632,9 @@ } }, "node_modules/@tauri-apps/cli-linux-riscv64-gnu": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.9.6.tgz", - "integrity": "sha512-fmp1hnulbqzl1GkXl4aTX9fV+ubHw2LqlLH1PE3BxZ11EQk+l/TmiEongjnxF0ie4kV8DQfDNJ1KGiIdWe1GvQ==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.10.0.tgz", + "integrity": "sha512-JO7s3TlSxshwsoKNCDkyvsx5gw2QAs/Y2GbR5UE2d5kkU138ATKoPOtxn8G1fFT1aDW4LH0rYAAfBpGkDyJJnw==", "cpu": [ "riscv64" ], @@ -1789,9 +1649,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.9.6.tgz", - "integrity": "sha512-vY0le8ad2KaV1PJr+jCd8fUF9VOjwwQP/uBuTJvhvKTloEwxYA/kAjKK9OpIslGA9m/zcnSo74czI6bBrm2sYA==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.10.0.tgz", + "integrity": "sha512-Uvh4SUUp4A6DVRSMWjelww0GnZI3PlVy7VS+DRF5napKuIehVjGl9XD0uKoCoxwAQBLctvipyEK+pDXpJeoHng==", "cpu": [ "x64" ], @@ -1806,9 +1666,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.9.6.tgz", - "integrity": "sha512-TOEuB8YCFZTWVDzsO2yW0+zGcoMiPPwcUgdnW1ODnmgfwccpnihDRoks+ABT1e3fHb1ol8QQWsHSCovb3o2ENQ==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.10.0.tgz", + "integrity": "sha512-AP0KRK6bJuTpQ8kMNWvhIpKUkQJfcPFeba7QshOQZjJ8wOS6emwTN4K5g/d3AbCMo0RRdnZWwu67MlmtJyxC1Q==", "cpu": [ "x64" ], @@ -1823,9 +1683,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.9.6.tgz", - "integrity": "sha512-ujmDGMRc4qRLAnj8nNG26Rlz9klJ0I0jmZs2BPpmNNf0gM/rcVHhqbEkAaHPTBVIrtUdf7bGvQAD2pyIiUrBHQ==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.10.0.tgz", + "integrity": "sha512-97DXVU3dJystrq7W41IX+82JEorLNY+3+ECYxvXWqkq7DBN6FsA08x/EFGE8N/b0LTOui9X2dvpGGoeZKKV08g==", "cpu": [ "arm64" ], @@ -1840,9 +1700,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.9.6.tgz", - "integrity": "sha512-S4pT0yAJgFX8QRCyKA1iKjZ9Q/oPjCZf66A/VlG5Yw54Nnr88J1uBpmenINbXxzyhduWrIXBaUbEY1K80ZbpMg==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.10.0.tgz", + "integrity": "sha512-EHyQ1iwrWy1CwMalEm9z2a6L5isQ121pe7FcA2xe4VWMJp+GHSDDGvbTv/OPdkt2Lyr7DAZBpZHM6nvlHXEc4A==", "cpu": [ "ia32" ], @@ -1857,9 +1717,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.9.6.tgz", - "integrity": "sha512-ldWuWSSkWbKOPjQMJoYVj9wLHcOniv7diyI5UAJ4XsBdtaFB0pKHQsqw/ItUma0VXGC7vB4E9fZjivmxur60aw==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.10.0.tgz", + "integrity": "sha512-NTpyQxkpzGmU6ceWBTY2xRIEaS0ZLbVx1HE1zTA3TY/pV3+cPoPPOs+7YScr4IMzXMtOw7tLw5LEXo5oIG3qaQ==", "cpu": [ "x64" ], @@ -1909,6 +1769,13 @@ "@tauri-apps/api": "^2.8.0" } }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1924,13 +1791,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.0.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.10.tgz", - "integrity": "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.0.tgz", + "integrity": "sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.16.0" + "undici-types": "~7.18.0" } }, "node_modules/@types/trusted-types": { @@ -1941,17 +1808,17 @@ "optional": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.1.tgz", - "integrity": "sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.0.tgz", + "integrity": "sha512-lRyPDLzNCuae71A3t9NEINBiTn7swyOhvUj3MyUOxb8x6g6vPEFoOU+ZRmGMusNC3X3YMhqMIX7i8ShqhT74Pw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.53.1", - "@typescript-eslint/type-utils": "8.53.1", - "@typescript-eslint/utils": "8.53.1", - "@typescript-eslint/visitor-keys": "8.53.1", + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/type-utils": "8.56.0", + "@typescript-eslint/utils": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" @@ -1964,22 +1831,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.53.1", - "eslint": "^8.57.0 || ^9.0.0", + "@typescript-eslint/parser": "^8.56.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.53.1.tgz", - "integrity": "sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.0.tgz", + "integrity": "sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.53.1", - "@typescript-eslint/types": "8.53.1", - "@typescript-eslint/typescript-estree": "8.53.1", - "@typescript-eslint/visitor-keys": "8.53.1", + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", "debug": "^4.4.3" }, "engines": { @@ -1990,19 +1857,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.53.1.tgz", - "integrity": "sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.0.tgz", + "integrity": "sha512-M3rnyL1vIQOMeWxTWIW096/TtVP+8W3p/XnaFflhmcFp+U4zlxUxWj4XwNs6HbDeTtN4yun0GNTTDBw/SvufKg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.53.1", - "@typescript-eslint/types": "^8.53.1", + "@typescript-eslint/tsconfig-utils": "^8.56.0", + "@typescript-eslint/types": "^8.56.0", "debug": "^4.4.3" }, "engines": { @@ -2017,14 +1884,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.1.tgz", - "integrity": "sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.0.tgz", + "integrity": "sha512-7UiO/XwMHquH+ZzfVCfUNkIXlp/yQjjnlYUyYz7pfvlK3/EyyN6BK+emDmGNyQLBtLGaYrTAI6KOw8tFucWL2w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.1", - "@typescript-eslint/visitor-keys": "8.53.1" + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2035,9 +1902,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.53.1.tgz", - "integrity": "sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.0.tgz", + "integrity": "sha512-bSJoIIt4o3lKXD3xmDh9chZcjCz5Lk8xS7Rxn+6l5/pKrDpkCwtQNQQwZ2qRPk7TkUYhrq3WPIHXOXlbXP0itg==", "dev": true, "license": "MIT", "engines": { @@ -2052,15 +1919,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.53.1.tgz", - "integrity": "sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.0.tgz", + "integrity": "sha512-qX2L3HWOU2nuDs6GzglBeuFXviDODreS58tLY/BALPC7iu3Fa+J7EOTwnX9PdNBxUI7Uh0ntP0YWGnxCkXzmfA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.1", - "@typescript-eslint/typescript-estree": "8.53.1", - "@typescript-eslint/utils": "8.53.1", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0", + "@typescript-eslint/utils": "8.56.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, @@ -2072,14 +1939,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.1.tgz", - "integrity": "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.0.tgz", + "integrity": "sha512-DBsLPs3GsWhX5HylbP9HNG15U0bnwut55Lx12bHB9MpXxQ+R5GC8MwQe+N1UFXxAeQDvEsEDY6ZYwX03K7Z6HQ==", "dev": true, "license": "MIT", "engines": { @@ -2091,16 +1958,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.1.tgz", - "integrity": "sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.0.tgz", + "integrity": "sha512-ex1nTUMWrseMltXUHmR2GAQ4d+WjkZCT4f+4bVsps8QEdh0vlBsaCokKTPlnqBFqqGaxilDNJG7b8dolW2m43Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.53.1", - "@typescript-eslint/tsconfig-utils": "8.53.1", - "@typescript-eslint/types": "8.53.1", - "@typescript-eslint/visitor-keys": "8.53.1", + "@typescript-eslint/project-service": "8.56.0", + "@typescript-eslint/tsconfig-utils": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", @@ -2119,16 +1986,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.1.tgz", - "integrity": "sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.0.tgz", + "integrity": "sha512-RZ3Qsmi2nFGsS+n+kjLAYDPVlrzf7UhTffrDIKr+h2yzAlYP/y5ZulU0yeDEPItos2Ph46JAL5P/On3pe7kDIQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.53.1", - "@typescript-eslint/types": "8.53.1", - "@typescript-eslint/typescript-estree": "8.53.1" + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2138,19 +2005,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.1.tgz", - "integrity": "sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.0.tgz", + "integrity": "sha512-q+SL+b+05Ud6LbEE35qe4A99P+htKTKVbyiNEe45eCbJFyh/HVK9QXwlrbz+Q4L8SOW4roxSVwXYj4DMBT7Ieg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.1", - "eslint-visitor-keys": "^4.2.1" + "@typescript-eslint/types": "8.56.0", + "eslint-visitor-keys": "^5.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2161,26 +2028,26 @@ } }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.0.tgz", + "integrity": "sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/@vitejs/plugin-vue": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.3.tgz", - "integrity": "sha512-TlGPkLFLVOY3T7fZrwdvKpjprR3s4fxRln0ORDo1VQ7HHyxJwTlrjKU3kpVWTlaAjIEuCTokmjkZnr8Tpc925w==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.4.tgz", + "integrity": "sha512-uM5iXipgYIn13UUQCZNdWkYk+sysBeA97d5mHsAoAt1u/wpN3+zxOmsVJWosuzX+IMGRzeYUNytztrYznboIkQ==", "dev": true, "license": "MIT", "dependencies": { - "@rolldown/pluginutils": "1.0.0-beta.53" + "@rolldown/pluginutils": "1.0.0-rc.2" }, "engines": { "node": "^20.19.0 || >=22.12.0" @@ -2191,68 +2058,68 @@ } }, "node_modules/@volar/language-core": { - "version": "2.4.27", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.27.tgz", - "integrity": "sha512-DjmjBWZ4tJKxfNC1F6HyYERNHPYS7L7OPFyCrestykNdUZMFYzI9WTyvwPcaNaHlrEUwESHYsfEw3isInncZxQ==", + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.28.tgz", + "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==", "dev": true, "license": "MIT", "dependencies": { - "@volar/source-map": "2.4.27" + "@volar/source-map": "2.4.28" } }, "node_modules/@volar/source-map": { - "version": "2.4.27", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.27.tgz", - "integrity": "sha512-ynlcBReMgOZj2i6po+qVswtDUeeBRCTgDurjMGShbm8WYZgJ0PA4RmtebBJ0BCYol1qPv3GQF6jK7C9qoVc7lg==", + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.28.tgz", + "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==", "dev": true, "license": "MIT" }, "node_modules/@volar/typescript": { - "version": "2.4.27", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.27.tgz", - "integrity": "sha512-eWaYCcl/uAPInSK2Lze6IqVWaBu/itVqR5InXcHXFyles4zO++Mglt3oxdgj75BDcv1Knr9Y93nowS8U3wqhxg==", + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.28.tgz", + "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "2.4.27", + "@volar/language-core": "2.4.28", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } }, "node_modules/@vue/compiler-core": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.27.tgz", - "integrity": "sha512-gnSBQjZA+//qDZen+6a2EdHqJ68Z7uybrMf3SPjEGgG4dicklwDVmMC1AeIHxtLVPT7sn6sH1KOO+tS6gwOUeQ==", + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.28.tgz", + "integrity": "sha512-kviccYxTgoE8n6OCw96BNdYlBg2GOWfBuOW4Vqwrt7mSKWKwFVvI8egdTltqRgITGPsTFYtKYfxIG8ptX2PJHQ==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@vue/shared": "3.5.27", - "entities": "^7.0.0", + "@babel/parser": "^7.29.0", + "@vue/shared": "3.5.28", + "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.27.tgz", - "integrity": "sha512-oAFea8dZgCtVVVTEC7fv3T5CbZW9BxpFzGGxC79xakTr6ooeEqmRuvQydIiDAkglZEAd09LgVf1RoDnL54fu5w==", + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.28.tgz", + "integrity": "sha512-/1ZepxAb159jKR1btkefDP+J2xuWL5V3WtleRmxaT+K2Aqiek/Ab/+Ebrw2pPj0sdHO8ViAyyJWfhXXOP/+LQA==", "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.27", - "@vue/shared": "3.5.27" + "@vue/compiler-core": "3.5.28", + "@vue/shared": "3.5.28" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.27.tgz", - "integrity": "sha512-sHZu9QyDPeDmN/MRoshhggVOWE5WlGFStKFwu8G52swATgSny27hJRWteKDSUUzUH+wp+bmeNbhJnEAel/auUQ==", + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.28.tgz", + "integrity": "sha512-6TnKMiNkd6u6VeVDhZn/07KhEZuBSn43Wd2No5zaP5s3xm8IqFTHBj84HJah4UepSUJTro5SoqqlOY22FKY96g==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@vue/compiler-core": "3.5.27", - "@vue/compiler-dom": "3.5.27", - "@vue/compiler-ssr": "3.5.27", - "@vue/shared": "3.5.27", + "@babel/parser": "^7.29.0", + "@vue/compiler-core": "3.5.28", + "@vue/compiler-dom": "3.5.28", + "@vue/compiler-ssr": "3.5.28", + "@vue/shared": "3.5.28", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.6", @@ -2260,13 +2127,13 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.27.tgz", - "integrity": "sha512-Sj7h+JHt512fV1cTxKlYhg7qxBvack+BGncSpH+8vnN+KN95iPIcqB5rsbblX40XorP+ilO7VIKlkuu3Xq2vjw==", + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.28.tgz", + "integrity": "sha512-JCq//9w1qmC6UGLWJX7RXzrGpKkroubey/ZFqTpvEIDJEKGgntuDMqkuWiZvzTzTA5h2qZvFBFHY7fAAa9475g==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.27", - "@vue/shared": "3.5.27" + "@vue/compiler-dom": "3.5.28", + "@vue/shared": "3.5.28" } }, "node_modules/@vue/devtools-api": { @@ -2276,13 +2143,13 @@ "license": "MIT" }, "node_modules/@vue/language-core": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.2.2.tgz", - "integrity": "sha512-5DAuhxsxBN9kbriklh3Q5AMaJhyOCNiQJvCskN9/30XOpdLiqZU9Q+WvjArP17ubdGEyZtBzlIeG5nIjEbNOrQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.2.5.tgz", + "integrity": "sha512-d3OIxN/+KRedeM5wQ6H6NIpwS3P5gC9nmyaHgBk+rO6dIsjY+tOh4UlPpiZbAh3YtLdCGEX4M16RmsBqPmJV+g==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "2.4.27", + "@volar/language-core": "2.4.28", "@vue/compiler-dom": "^3.5.0", "@vue/shared": "^3.5.0", "alien-signals": "^3.0.0", @@ -2292,59 +2159,59 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.27.tgz", - "integrity": "sha512-vvorxn2KXfJ0nBEnj4GYshSgsyMNFnIQah/wczXlsNXt+ijhugmW+PpJ2cNPe4V6jpnBcs0MhCODKllWG+nvoQ==", + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.28.tgz", + "integrity": "sha512-gr5hEsxvn+RNyu9/9o1WtdYdwDjg5FgjUSBEkZWqgTKlo/fvwZ2+8W6AfKsc9YN2k/+iHYdS9vZYAhpi10kNaw==", "license": "MIT", "dependencies": { - "@vue/shared": "3.5.27" + "@vue/shared": "3.5.28" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.27.tgz", - "integrity": "sha512-fxVuX/fzgzeMPn/CLQecWeDIFNt3gQVhxM0rW02Tvp/YmZfXQgcTXlakq7IMutuZ/+Ogbn+K0oct9J3JZfyk3A==", + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.28.tgz", + "integrity": "sha512-POVHTdbgnrBBIpnbYU4y7pOMNlPn2QVxVzkvEA2pEgvzbelQq4ZOUxbp2oiyo+BOtiYlm8Q44wShHJoBvDPAjQ==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.27", - "@vue/shared": "3.5.27" + "@vue/reactivity": "3.5.28", + "@vue/shared": "3.5.28" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.27.tgz", - "integrity": "sha512-/QnLslQgYqSJ5aUmb5F0z0caZPGHRB8LEAQ1s81vHFM5CBfnun63rxhvE/scVb/j3TbBuoZwkJyiLCkBluMpeg==", + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.28.tgz", + "integrity": "sha512-4SXxSF8SXYMuhAIkT+eBRqOkWEfPu6nhccrzrkioA6l0boiq7sp18HCOov9qWJA5HML61kW8p/cB4MmBiG9dSA==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.27", - "@vue/runtime-core": "3.5.27", - "@vue/shared": "3.5.27", + "@vue/reactivity": "3.5.28", + "@vue/runtime-core": "3.5.28", + "@vue/shared": "3.5.28", "csstype": "^3.2.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.27.tgz", - "integrity": "sha512-qOz/5thjeP1vAFc4+BY3Nr6wxyLhpeQgAE/8dDtKo6a6xdk+L4W46HDZgNmLOBUDEkFXV3G7pRiUqxjX0/2zWA==", + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.28.tgz", + "integrity": "sha512-pf+5ECKGj8fX95bNincbzJ6yp6nyzuLDhYZCeFxUNp8EBrQpPpQaLX3nNCp49+UbgbPun3CeVE+5CXVV1Xydfg==", "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.5.27", - "@vue/shared": "3.5.27" + "@vue/compiler-ssr": "3.5.28", + "@vue/shared": "3.5.28" }, "peerDependencies": { - "vue": "3.5.27" + "vue": "3.5.28" } }, "node_modules/@vue/shared": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.27.tgz", - "integrity": "sha512-dXr/3CgqXsJkZ0n9F3I4elY8wM9jMJpP3pvRG52r6m0tu/MsAFIe6JpXVGeNMd/D9F4hQynWT8Rfuj0bdm9kFQ==", + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.28.tgz", + "integrity": "sha512-cfWa1fCGBxrvaHRhvV3Is0MgmrbSCxYTXCSCau2I0a1Xw1N1pHAvkWCiXPRAqjvToILvguNyEwjevUqAuBQWvQ==", "license": "MIT" }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", "bin": { @@ -2388,29 +2255,6 @@ "dev": true, "license": "MIT" }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2418,13 +2262,13 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", - "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", + "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, @@ -2465,53 +2309,6 @@ "node": ">= 0.4" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2524,13 +2321,6 @@ "node": ">= 0.8" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -2566,9 +2356,9 @@ "license": "MIT" }, "node_modules/daisyui": { - "version": "5.5.14", - "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.5.14.tgz", - "integrity": "sha512-L47rvw7I7hK68TA97VB8Ee0woHew+/ohR6Lx6Ah/krfISOqcG4My7poNpX5Mo5/ytMxiR40fEaz6njzDi7cuSg==", + "version": "5.5.19", + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.5.19.tgz", + "integrity": "sha512-pbFAkl1VCEh/MPCeclKL61I/MqRIFFhNU7yiXoDDRapXN4/qNCoMxeCCswyxEEhqL5eiTTfwHvucFtOE71C9sA==", "license": "MIT", "funding": { "url": "https://github.com/saadeghi/daisyui?sponsor=1" @@ -2642,14 +2432,14 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.18.4", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", - "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", + "version": "5.19.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", + "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.0" }, "engines": { "node": ">=10.13.0" @@ -2713,9 +2503,9 @@ } }, "node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -2726,32 +2516,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.2", - "@esbuild/android-arm": "0.27.2", - "@esbuild/android-arm64": "0.27.2", - "@esbuild/android-x64": "0.27.2", - "@esbuild/darwin-arm64": "0.27.2", - "@esbuild/darwin-x64": "0.27.2", - "@esbuild/freebsd-arm64": "0.27.2", - "@esbuild/freebsd-x64": "0.27.2", - "@esbuild/linux-arm": "0.27.2", - "@esbuild/linux-arm64": "0.27.2", - "@esbuild/linux-ia32": "0.27.2", - "@esbuild/linux-loong64": "0.27.2", - "@esbuild/linux-mips64el": "0.27.2", - "@esbuild/linux-ppc64": "0.27.2", - "@esbuild/linux-riscv64": "0.27.2", - "@esbuild/linux-s390x": "0.27.2", - "@esbuild/linux-x64": "0.27.2", - "@esbuild/netbsd-arm64": "0.27.2", - "@esbuild/netbsd-x64": "0.27.2", - "@esbuild/openbsd-arm64": "0.27.2", - "@esbuild/openbsd-x64": "0.27.2", - "@esbuild/openharmony-arm64": "0.27.2", - "@esbuild/sunos-x64": "0.27.2", - "@esbuild/win32-arm64": "0.27.2", - "@esbuild/win32-ia32": "0.27.2", - "@esbuild/win32-x64": "0.27.2" + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" } }, "node_modules/escape-string-regexp": { @@ -2768,33 +2558,30 @@ } }, "node_modules/eslint": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", - "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.0.1.tgz", + "integrity": "sha512-20MV9SUdeN6Jd84xESsKhRly+/vxI+hwvpBMA93s+9dAcjdCuCojn4IqUGS3lvVaqjVYGYHSRMCpeFtF2rQYxQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.1", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.2", - "@eslint/plugin-kit": "^0.4.1", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.2", + "@eslint/config-helpers": "^0.5.2", + "@eslint/core": "^1.1.0", + "@eslint/plugin-kit": "^0.6.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", - "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", + "eslint-scope": "^9.1.1", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.1.1", + "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", @@ -2804,8 +2591,7 @@ "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "minimatch": "^10.2.1", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -2813,7 +2599,7 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://eslint.org/donate" @@ -2828,9 +2614,9 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.7.0.tgz", - "integrity": "sha512-r2XFCK4qlo1sxEoAMIoTTX0PZAdla0JJDt1fmYiworZUX67WeEGqm+JbyAg3M+pGiJ5U6Mp5WQbontXWtIW7TA==", + "version": "10.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.8.0.tgz", + "integrity": "sha512-f1J/tcbnrpgC8suPN5AtdJ5MQjuXbSU9pGRSSYAuF3SHoiYCOdEX6O22pLaRyLHXvDcOe+O5ENgc1owQ587agA==", "dev": true, "license": "MIT", "dependencies": { @@ -2847,7 +2633,7 @@ "peerDependencies": { "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "vue-eslint-parser": "^10.0.0" }, "peerDependenciesMeta": { @@ -2860,17 +2646,19 @@ } }, "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.1.tgz", + "integrity": "sha512-GaUN0sWim5qc8KVErfPBWmc31LEsOkrUJbvJZV+xuL3u2phMUK4HIvXlWAakfC8W4nzlK+chPEAkYOYb5ZScIw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2889,25 +2677,40 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz", + "integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "jackspeak": "^4.2.3" + }, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", + "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2924,44 +2727,47 @@ } }, "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.1.tgz", + "integrity": "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^5.0.2" }, "engines": { - "node": "*" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.1.1.tgz", + "integrity": "sha512-AVHPqQoZYc+RUM4/3Ly5udlZY/U4LS8pIG05jEjWM2lQMU/oaZ7qshzAl2YP1tfNmXfftH3ohurfwNAug+MnsQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" + "eslint-visitor-keys": "^5.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -3023,6 +2829,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, "license": "MIT" }, "node_modules/fast-json-stable-stringify": { @@ -3218,19 +3025,6 @@ "node": ">=10.13.0" } }, - "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -3256,16 +3050,6 @@ "integrity": "sha512-P8/mMxVLU7o4+55+1TCnQrPmgjPKnwkzkXOK1asnR9Jg2lna4tEY5qBJjMmAaOBDDZWtlRjBXjLa0w53G/uBLA==", "license": "Standard 'no charge' license: https://gsap.com/standard-license." }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -3315,23 +3099,6 @@ "node": ">= 4" } }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -3372,6 +3139,22 @@ "dev": true, "license": "ISC" }, + "node_modules/jackspeak": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz", + "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^9.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", @@ -3382,19 +3165,6 @@ "jiti": "lib/jiti-cli.mjs" } }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -3426,15 +3196,6 @@ "json-buffer": "3.0.1" } }, - "node_modules/klona": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3450,9 +3211,9 @@ } }, "node_modules/lightningcss": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", - "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", + "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -3466,23 +3227,23 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-android-arm64": "1.30.2", - "lightningcss-darwin-arm64": "1.30.2", - "lightningcss-darwin-x64": "1.30.2", - "lightningcss-freebsd-x64": "1.30.2", - "lightningcss-linux-arm-gnueabihf": "1.30.2", - "lightningcss-linux-arm64-gnu": "1.30.2", - "lightningcss-linux-arm64-musl": "1.30.2", - "lightningcss-linux-x64-gnu": "1.30.2", - "lightningcss-linux-x64-musl": "1.30.2", - "lightningcss-win32-arm64-msvc": "1.30.2", - "lightningcss-win32-x64-msvc": "1.30.2" + "lightningcss-android-arm64": "1.31.1", + "lightningcss-darwin-arm64": "1.31.1", + "lightningcss-darwin-x64": "1.31.1", + "lightningcss-freebsd-x64": "1.31.1", + "lightningcss-linux-arm-gnueabihf": "1.31.1", + "lightningcss-linux-arm64-gnu": "1.31.1", + "lightningcss-linux-arm64-musl": "1.31.1", + "lightningcss-linux-x64-gnu": "1.31.1", + "lightningcss-linux-x64-musl": "1.31.1", + "lightningcss-win32-arm64-msvc": "1.31.1", + "lightningcss-win32-x64-msvc": "1.31.1" } }, "node_modules/lightningcss-android-arm64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", - "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz", + "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==", "cpu": [ "arm64" ], @@ -3501,9 +3262,9 @@ } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", - "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz", + "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==", "cpu": [ "arm64" ], @@ -3522,9 +3283,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", - "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz", + "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==", "cpu": [ "x64" ], @@ -3543,9 +3304,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", - "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz", + "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==", "cpu": [ "x64" ], @@ -3564,9 +3325,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", - "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz", + "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==", "cpu": [ "arm" ], @@ -3585,9 +3346,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", - "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz", + "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==", "cpu": [ "arm64" ], @@ -3606,9 +3367,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", - "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz", + "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==", "cpu": [ "arm64" ], @@ -3627,9 +3388,9 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", - "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz", + "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==", "cpu": [ "x64" ], @@ -3648,9 +3409,9 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", - "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz", + "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==", "cpu": [ "x64" ], @@ -3669,9 +3430,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", - "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz", + "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==", "cpu": [ "arm64" ], @@ -3690,9 +3451,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", - "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz", + "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==", "cpu": [ "x64" ], @@ -3726,23 +3487,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lottie-web": { - "version": "5.12.2", - "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", - "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==", - "license": "MIT" - }, "node_modules/lucide-vue-next": { - "version": "0.562.0", - "resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-0.562.0.tgz", - "integrity": "sha512-LN0BLGKMFulv0lnfK29r14DcngRUhIqdcaL0zXTt2o0oS9odlrjCGaU3/X9hIihOjjN8l8e+Y9G/famcNYaI7Q==", + "version": "0.575.0", + "resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-0.575.0.tgz", + "integrity": "sha512-UHzA3cYMCgBLyGay5R9IQaidwV0NLocx7cIBnFt8vJ9Xhl6IM/oKD0fUhoCUuouFta15SX1rLXVoko9s3TzWMA==", "license": "ISC", "peerDependencies": { "vue": ">=3.0.1" @@ -3927,19 +3675,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -4038,6 +3773,22 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -4054,20 +3805,10 @@ "node": ">=6" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/rollup": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.56.0.tgz", - "integrity": "sha512-9FwVqlgUHzbXtDg9RCMgodF3Ua4Na6Gau+Sdt9vyCN4RhHfVKX2DCHy3BjMLTDd47ITDhYAnTwGulWTblJSDLg==", + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", + "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", "dev": true, "license": "MIT", "dependencies": { @@ -4081,38 +3822,38 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.56.0", - "@rollup/rollup-android-arm64": "4.56.0", - "@rollup/rollup-darwin-arm64": "4.56.0", - "@rollup/rollup-darwin-x64": "4.56.0", - "@rollup/rollup-freebsd-arm64": "4.56.0", - "@rollup/rollup-freebsd-x64": "4.56.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.56.0", - "@rollup/rollup-linux-arm-musleabihf": "4.56.0", - "@rollup/rollup-linux-arm64-gnu": "4.56.0", - "@rollup/rollup-linux-arm64-musl": "4.56.0", - "@rollup/rollup-linux-loong64-gnu": "4.56.0", - "@rollup/rollup-linux-loong64-musl": "4.56.0", - "@rollup/rollup-linux-ppc64-gnu": "4.56.0", - "@rollup/rollup-linux-ppc64-musl": "4.56.0", - "@rollup/rollup-linux-riscv64-gnu": "4.56.0", - "@rollup/rollup-linux-riscv64-musl": "4.56.0", - "@rollup/rollup-linux-s390x-gnu": "4.56.0", - "@rollup/rollup-linux-x64-gnu": "4.56.0", - "@rollup/rollup-linux-x64-musl": "4.56.0", - "@rollup/rollup-openbsd-x64": "4.56.0", - "@rollup/rollup-openharmony-arm64": "4.56.0", - "@rollup/rollup-win32-arm64-msvc": "4.56.0", - "@rollup/rollup-win32-ia32-msvc": "4.56.0", - "@rollup/rollup-win32-x64-gnu": "4.56.0", - "@rollup/rollup-win32-x64-msvc": "4.56.0", + "@rollup/rollup-android-arm-eabi": "4.57.1", + "@rollup/rollup-android-arm64": "4.57.1", + "@rollup/rollup-darwin-arm64": "4.57.1", + "@rollup/rollup-darwin-x64": "4.57.1", + "@rollup/rollup-freebsd-arm64": "4.57.1", + "@rollup/rollup-freebsd-x64": "4.57.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", + "@rollup/rollup-linux-arm-musleabihf": "4.57.1", + "@rollup/rollup-linux-arm64-gnu": "4.57.1", + "@rollup/rollup-linux-arm64-musl": "4.57.1", + "@rollup/rollup-linux-loong64-gnu": "4.57.1", + "@rollup/rollup-linux-loong64-musl": "4.57.1", + "@rollup/rollup-linux-ppc64-gnu": "4.57.1", + "@rollup/rollup-linux-ppc64-musl": "4.57.1", + "@rollup/rollup-linux-riscv64-gnu": "4.57.1", + "@rollup/rollup-linux-riscv64-musl": "4.57.1", + "@rollup/rollup-linux-s390x-gnu": "4.57.1", + "@rollup/rollup-linux-x64-gnu": "4.57.1", + "@rollup/rollup-linux-x64-musl": "4.57.1", + "@rollup/rollup-openbsd-x64": "4.57.1", + "@rollup/rollup-openharmony-arm64": "4.57.1", + "@rollup/rollup-win32-arm64-msvc": "4.57.1", + "@rollup/rollup-win32-ia32-msvc": "4.57.1", + "@rollup/rollup-win32-x64-gnu": "4.57.1", + "@rollup/rollup-win32-x64-msvc": "4.57.1", "fsevents": "~2.3.2" } }, "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { @@ -4160,36 +3901,10 @@ "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", "license": "MIT" }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/tailwindcss": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", - "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.0.tgz", + "integrity": "sha512-yYzTZ4++b7fNYxFfpnberEEKu43w44aqDMNM9MHMmcKuCH7lL8jJ4yJ7LGHv7rSwiqM0nkiobF9I6cLlpS2P7Q==", "dev": true, "license": "MIT" }, @@ -4265,9 +3980,9 @@ } }, "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", "dev": true, "license": "MIT" }, @@ -4371,16 +4086,16 @@ "license": "MIT" }, "node_modules/vue": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.27.tgz", - "integrity": "sha512-aJ/UtoEyFySPBGarREmN4z6qNKpbEguYHMmXSiOGk69czc+zhs0NF6tEFrY8TZKAl8N/LYAkd4JHVd5E/AsSmw==", + "version": "3.5.28", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.28.tgz", + "integrity": "sha512-BRdrNfeoccSoIZeIhyPBfvWSLFP4q8J3u8Ju8Ug5vu3LdD+yTM13Sg4sKtljxozbnuMu1NB1X5HBHRYUzFocKg==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.27", - "@vue/compiler-sfc": "3.5.27", - "@vue/runtime-dom": "3.5.27", - "@vue/server-renderer": "3.5.27", - "@vue/shared": "3.5.27" + "@vue/compiler-dom": "3.5.28", + "@vue/compiler-sfc": "3.5.28", + "@vue/runtime-dom": "3.5.28", + "@vue/server-renderer": "3.5.28", + "@vue/shared": "3.5.28" }, "peerDependencies": { "typescript": "*" @@ -4392,17 +4107,16 @@ } }, "node_modules/vue-eslint-parser": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.2.0.tgz", - "integrity": "sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.4.0.tgz", + "integrity": "sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "debug": "^4.4.0", - "eslint-scope": "^8.2.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.2.0 || ^9.0.0", + "eslint-visitor-keys": "^4.2.0 || ^5.0.0", + "espree": "^10.3.0 || ^11.0.0", "esquery": "^1.6.0", "semver": "^7.6.3" }, @@ -4413,18 +4127,17 @@ "url": "https://github.com/sponsors/mysticatea" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0" } }, "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.0.tgz", + "integrity": "sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -4451,14 +4164,14 @@ } }, "node_modules/vue-tsc": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.2.2.tgz", - "integrity": "sha512-r9YSia/VgGwmbbfC06hDdAatH634XJ9nVl6Zrnz1iK4ucp8Wu78kawplXnIDa3MSu1XdQQePTHLXYwPDWn+nyQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.2.5.tgz", + "integrity": "sha512-/htfTCMluQ+P2FISGAooul8kO4JMheOTCbCy4M6dYnYYjqLe3BExZudAua6MSIKSFYQtFOYAll7XobYwcpokGA==", "dev": true, "license": "MIT", "dependencies": { - "@volar/typescript": "2.4.27", - "@vue/language-core": "3.2.2" + "@volar/typescript": "2.4.28", + "@vue/language-core": "3.2.5" }, "bin": { "vue-tsc": "bin/vue-tsc.js" @@ -4467,23 +4180,6 @@ "typescript": ">=5.0.0" } }, - "node_modules/vue3-lottie": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/vue3-lottie/-/vue3-lottie-3.3.1.tgz", - "integrity": "sha512-60uQmx4eefi3FdPjAxWnblrgJJjnVTXUA6e4BAI3jGzgOSR76pyzL1rrWDiyPmMFo4mTw4wGTW6Gbkg3HR1mYw==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "klona": "^2.0.6", - "lottie-web": "5.12.2" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "vue": "^3.2" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index a8156fc5..bc6e19e1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "collapseloader", "private": true, - "version": "0.2.7", + "version": "0.2.8", "type": "module", "scripts": { "dev": "vite", @@ -12,37 +12,39 @@ "tauri:dev": "tauri dev", "check": "vue-tsc --noEmit", "lint": "eslint --ext .ts,.tsx,.vue src", - "lint:fix": "eslint --ext .ts,.tsx,.vue src --fix" + "lint:fix": "eslint --ext .ts,.tsx,.vue src --fix", + "format": "prettier --write \"src/**/*\"" }, "dependencies": { "@guolao/vue-monaco-editor": "1.6.0", - "@sentry/vue": "^10.36.0", - "@tauri-apps/api": "2.9.1", + "@stomp/stompjs": "^7.3.0", + "@tauri-apps/api": "2.10.1", "@tauri-apps/plugin-dialog": "2.6.0", "@tauri-apps/plugin-fs": "2.4.5", "@tauri-apps/plugin-notification": "2.3.3", "@tauri-apps/plugin-opener": "2.5.3", - "axios": "1.13.2", - "daisyui": "5.5.14", + "axios": "1.13.5", + "daisyui": "5.5.19", "gsap": "3.14.2", - "lucide-vue-next": "0.562.0", + "lucide-vue-next": "0.575.0", "monaco-editor": "^0.55.1", - "vue": "3.5.27", - "vue-i18n": "11.2.8", - "vue3-lottie": "3.3.1" + "vue": "3.5.28", + "vue-i18n": "11.2.8" }, "devDependencies": { - "@tailwindcss/vite": "4.1.18", - "@tauri-apps/cli": "2.9.6", - "@types/node": "25.0.10", - "@typescript-eslint/eslint-plugin": "8.53.1", - "@typescript-eslint/parser": "8.53.1", - "@vitejs/plugin-vue": "6.0.3", - "eslint": "9.39.2", - "eslint-plugin-vue": "10.7.0", - "tailwindcss": "4.1.18", + "@tailwindcss/vite": "4.2.0", + "@tauri-apps/cli": "2.10.0", + "@types/node": "25.3.0", + "@typescript-eslint/eslint-plugin": "8.56.0", + "@typescript-eslint/parser": "8.56.0", + "@vitejs/plugin-vue": "6.0.4", + "eslint": "^10.0.1", + "eslint-plugin-vue": "10.8.0", + "vue-eslint-parser": "^10.4.0", + "prettier": "3.8.1", + "tailwindcss": "4.2.0", "typescript": "5.9.3", "vite": "7.3.1", - "vue-tsc": "3.2.2" + "vue-tsc": "3.2.5" } -} +} \ No newline at end of file diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 55768d44..68bfcb22 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -16,7 +16,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -54,9 +54,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" [[package]] name = "ascii" @@ -157,7 +157,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -192,7 +192,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -232,9 +232,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.15.3" +version = "1.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e84ce723ab67259cfeb9877c6a639ee9eb7a27b28123abd71db7f0d5d0cc9d86" +checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256" dependencies = [ "aws-lc-sys", "zeroize", @@ -242,9 +242,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a442ece363113bd4bd4c8b18977a7798dd4d3c3383f34fb61936960e8f4ad8" +checksum = "5c34dda4df7017c8db52132f0f8a2e0f8161649d15723ed63fc00c82d0f2081a" dependencies = [ "cc", "cmake", @@ -272,9 +272,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" dependencies = [ "serde_core", ] @@ -288,15 +288,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-buffer" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96eb4cdd6cf1b31d671e9efe75c5d1ec614776856cefbe109ca373554a6d514f" -dependencies = [ - "hybrid-array", -] - [[package]] name = "block2" version = "0.6.2" @@ -359,9 +350,9 @@ checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "bytemuck" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" [[package]] name = "byteorder" @@ -371,9 +362,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] @@ -393,7 +384,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cairo-sys-rs", "glib", "libc", @@ -456,9 +447,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.53" +version = "1.2.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755d2fce177175ffca841e9a06afdb2c4ab0f593d53b4dee48147dfaade85932" +checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" dependencies = [ "find-msvc-tools", "jobserver", @@ -480,7 +471,7 @@ checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" dependencies = [ "byteorder", "fnv", - "uuid 1.19.0", + "uuid 1.21.0", ] [[package]] @@ -505,6 +496,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.0", +] + [[package]] name = "chrono" version = "0.4.43" @@ -525,7 +527,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common 0.1.7", + "crypto-common", "inout", ] @@ -540,7 +542,7 @@ dependencies = [ [[package]] name = "collapseloader" -version = "0.2.7" +version = "0.2.8" dependencies = [ "base64 0.22.1", "chrono", @@ -553,12 +555,12 @@ dependencies = [ "open", "opener", "paste", - "rand 0.9.2", - "reqwest 0.13.1", + "rand 0.10.0", + "reqwest", "semver", "serde", "serde_json", - "sha2 0.11.0-rc.3", + "sha2", "socket2", "sysinfo", "tauri", @@ -571,7 +573,7 @@ dependencies = [ "tauri-plugin-single-instance", "thiserror 2.0.18", "tokio", - "uuid 1.19.0", + "uuid 1.21.0", "windows 0.62.2", "winreg", "zip", @@ -605,12 +607,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "const-oid" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" - [[package]] name = "const-random" version = "0.1.18" @@ -633,9 +629,9 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] name = "convert_case" @@ -685,7 +681,7 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.10.1", "core-graphics-types", "foreign-types", @@ -698,7 +694,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.10.1", "libc", ] @@ -713,20 +709,14 @@ dependencies = [ ] [[package]] -name = "crc" -version = "3.3.0" +name = "cpufeatures" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ - "crc-catalog", + "libc", ] -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - [[package]] name = "crc32fast" version = "1.5.0" @@ -767,15 +757,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "crypto-common" -version = "0.2.0-rc.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d2bcc93d5cde6659e8649fc412894417ebc14dee54cfc6ee439c683a4a58342" -dependencies = [ - "hybrid-array", -] - [[package]] name = "cssparser" version = "0.29.6" @@ -800,7 +781,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -810,7 +791,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -834,7 +815,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -845,7 +826,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -874,7 +855,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -883,22 +864,11 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", - "crypto-common 0.1.7", + "block-buffer", + "crypto-common", "subtle", ] -[[package]] -name = "digest" -version = "0.11.0-rc.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca14c221bd9052fd2da7c34a2eeb5ae54732db28be47c35937be71793d675422" -dependencies = [ - "block-buffer 0.11.0", - "const-oid", - "crypto-common 0.2.0-rc.11", -] - [[package]] name = "dirs" version = "6.0.0" @@ -922,9 +892,9 @@ dependencies = [ [[package]] name = "discord-rich-presence" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ead3c5edc7e048c317c6fc4a7e24aff0c7e4c136918e2ba38106a385b2cc53a5" +checksum = "90c55d69cab17c19677ce3a5f8face993a9e6eaf847fecac3547f3a3ff4a2494" dependencies = [ "log", "serde", @@ -947,7 +917,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2", "libc", "objc2", @@ -961,7 +931,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -984,7 +954,7 @@ checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -1097,7 +1067,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -1181,15 +1151,15 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "flate2" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", @@ -1202,6 +1172,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "foreign-types" version = "0.5.0" @@ -1220,7 +1196,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -1272,9 +1248,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" @@ -1289,9 +1265,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-lite" @@ -1308,32 +1284,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-core", "futures-io", @@ -1342,7 +1318,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -1502,6 +1477,22 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "rand_core 0.10.0", + "wasip2", + "wasip3", + "wasm-bindgen", +] + [[package]] name = "gio" version = "0.18.4" @@ -1540,7 +1531,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "futures-channel", "futures-core", "futures-executor", @@ -1568,7 +1559,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -1647,7 +1638,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -1681,6 +1672,15 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + [[package]] name = "hashbrown" version = "0.16.1" @@ -1717,7 +1717,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -1771,15 +1771,6 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" -[[package]] -name = "hybrid-array" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f471e0a81b2f90ffc0cb2f951ae04da57de8baa46fa99112b062a5173a5088d0" -dependencies = [ - "typenum", -] - [[package]] name = "hyper" version = "1.8.1" @@ -1820,14 +1811,13 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64 0.22.1", "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", @@ -1846,9 +1836,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1870,9 +1860,9 @@ dependencies = [ [[package]] name = "ico" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc50b891e4acf8fe0e71ef88ec43ad82ee07b3810ad09de10f1d01f072ed4b98" +checksum = "3e795dff5605e0f04bff85ca41b51a96b83e80b281e96231bcaaf1ac35103371" dependencies = [ "byteorder", "png", @@ -1959,6 +1949,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -2170,7 +2166,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "serde", "unicode-segmentation", ] @@ -2193,6 +2189,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libappindicator" version = "0.9.0" @@ -2225,9 +2227,9 @@ checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7" [[package]] name = "libc" -version = "0.2.180" +version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] name = "libloading" @@ -2245,7 +2247,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "libc", ] @@ -2284,12 +2286,11 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" [[package]] name = "lzma-rust2" -version = "0.15.7" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1670343e58806300d87950e3401e820b519b9384281bbabfb15e3636689ffd69" +checksum = "47bb1e988e6fb779cf720ad431242d3f03167c1b3f2b1aae7f1a94b2495b36ae" dependencies = [ - "crc", - "sha2 0.10.9", + "sha2", ] [[package]] @@ -2332,7 +2333,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -2349,9 +2350,9 @@ checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memoffset" @@ -2412,9 +2413,9 @@ dependencies = [ [[package]] name = "native-dialog" -version = "0.9.4" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89853bb05334e192e6646290ea94ca31bcb80443f25ad40ebf478b6dafb08d6c" +checksum = "3b2373fb763ea6962e8c586571c7f9c5d8c995f9777cbdebbe0180263691bd4b" dependencies = [ "ascii", "block2", @@ -2440,7 +2441,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "jni-sys", "log", "ndk-sys", @@ -2496,9 +2497,9 @@ dependencies = [ [[package]] name = "notify-rust" -version = "4.11.7" +version = "4.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6442248665a5aa2514e794af3b39661a8e73033b1cc5e59899e1276117ee4400" +checksum = "21af20a1b50be5ac5861f74af1a863da53a11c38684d9818d82f1c42f7fdc6c2" dependencies = [ "futures-lite", "log", @@ -2519,9 +2520,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" [[package]] name = "num-traits" @@ -2551,7 +2552,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -2570,7 +2571,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2", "libc", "objc2", @@ -2591,7 +2592,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "objc2", "objc2-foundation", ] @@ -2602,7 +2603,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "objc2", "objc2-foundation", ] @@ -2613,7 +2614,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "dispatch2", "objc2", ] @@ -2624,7 +2625,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "dispatch2", "objc2", "objc2-core-foundation", @@ -2647,7 +2648,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "objc2", "objc2-core-foundation", "objc2-core-graphics", @@ -2659,7 +2660,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "objc2", "objc2-core-foundation", "objc2-core-graphics", @@ -2687,7 +2688,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2", "libc", "objc2", @@ -2710,7 +2711,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "objc2", "objc2-core-foundation", ] @@ -2731,7 +2732,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "objc2", "objc2-core-foundation", "objc2-foundation", @@ -2743,7 +2744,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "objc2", "objc2-core-foundation", ] @@ -2754,7 +2755,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "objc2", "objc2-core-foundation", "objc2-foundation", @@ -2766,7 +2767,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2", "objc2", "objc2-app-kit", @@ -2796,20 +2797,20 @@ dependencies = [ [[package]] name = "opener" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb9024962ab91e00c89d2a14352a8d0fc1a64346bf96f1839b45c09149564e47" +checksum = "a2fa337e0cf13357c13ef1dc108df1333eb192f75fc170bea03fcf1fd404c2ee" dependencies = [ "bstr", "normpath", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "openssl-probe" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "option-ext" @@ -2909,7 +2910,7 @@ version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ - "digest 0.10.7", + "digest", "hmac", ] @@ -3023,7 +3024,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -3050,7 +3051,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher 1.0.1", + "siphasher 1.0.2", ] [[package]] @@ -3139,9 +3140,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppmd-rust" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d558c559f0450f16f2a27a1f017ef38468c1090c9ce63c8e51366232d53717b4" +checksum = "efca4c95a19a79d1c98f791f10aebd5c1363b473244630bb7dbde1dc98455a24" [[package]] name = "ppv-lite86" @@ -3158,6 +3159,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.115", +] + [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -3219,9 +3230,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.105" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -3302,9 +3313,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -3350,6 +3361,17 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +dependencies = [ + "chacha20", + "getrandom 0.4.1", + "rand_core 0.10.0", +] + [[package]] name = "rand_chacha" version = "0.2.2" @@ -3407,6 +3429,12 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_core" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" + [[package]] name = "rand_hc" version = "0.2.0" @@ -3437,7 +3465,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] @@ -3468,14 +3496,14 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -3485,9 +3513,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -3496,50 +3524,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" - -[[package]] -name = "reqwest" -version = "0.12.28" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "js-sys", - "log", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-util", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", -] +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" [[package]] name = "reqwest" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" dependencies = [ "base64 0.22.1", "bytes", @@ -3648,7 +3641,7 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys", @@ -3736,12 +3729,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" -[[package]] -name = "ryu" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" - [[package]] name = "same-file" version = "1.0.6" @@ -3772,7 +3759,7 @@ dependencies = [ "serde", "serde_json", "url", - "uuid 1.19.0", + "uuid 1.21.0", ] [[package]] @@ -3789,9 +3776,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e910108742c57a770f492731f99be216a52fadd361b06c8fb59d74ccc267d2" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "dyn-clone", "ref-cast", @@ -3808,7 +3795,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -3823,7 +3810,7 @@ version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -3907,7 +3894,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -3918,7 +3905,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -3942,7 +3929,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -3963,18 +3950,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - [[package]] name = "serde_with" version = "3.16.1" @@ -3987,7 +3962,7 @@ dependencies = [ "indexmap 1.9.3", "indexmap 2.13.0", "schemars 0.9.0", - "schemars 1.2.0", + "schemars 1.2.1", "serde_core", "serde_json", "serde_with_macros", @@ -4003,7 +3978,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -4025,7 +4000,7 @@ checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -4045,8 +4020,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", - "digest 0.10.7", + "cpufeatures 0.2.17", + "digest", ] [[package]] @@ -4056,19 +4031,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.11.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d43dc0354d88b791216bb5c1bfbb60c0814460cc653ae0ebd71f286d0bd927" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.11.0-rc.7", + "cpufeatures 0.2.17", + "digest", ] [[package]] @@ -4101,15 +4065,15 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -4119,9 +4083,9 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" dependencies = [ "libc", "windows-sys 0.60.2", @@ -4242,9 +4206,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.114" +version = "2.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +checksum = "6e614ed320ac28113fa64972c4262d5dbc89deacdfd00c34a3e4cea073243c12" dependencies = [ "proc-macro2", "quote", @@ -4268,7 +4232,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -4287,11 +4251,11 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -4325,7 +4289,7 @@ version = "0.34.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3a753bdc39c07b192151523a3f77cd0394aa75413802c883a0f6f6a0e5ee2e7" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2", "core-foundation 0.10.1", "core-graphics", @@ -4367,7 +4331,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -4378,9 +4342,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.9.5" +version = "2.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a3868da5508446a7cd08956d523ac3edf0a8bc20bf7e4038f9a95c2800d2033" +checksum = "463ae8677aa6d0f063a900b9c41ecd4ac2b7ca82f0b058cc4491540e55b20129" dependencies = [ "anyhow", "bytes", @@ -4406,7 +4370,7 @@ dependencies = [ "percent-encoding", "plist", "raw-window-handle", - "reqwest 0.12.28", + "reqwest", "serde", "serde_json", "serde_repr", @@ -4429,9 +4393,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.5.3" +version = "2.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17fcb8819fd16463512a12f531d44826ce566f486d7ccd211c9c8cebdaec4e08" +checksum = "ca7bd893329425df750813e95bd2b643d5369d929438da96d5bbb7cc2c918f74" dependencies = [ "anyhow", "cargo_toml", @@ -4451,9 +4415,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa9844cefcf99554a16e0a278156ae73b0d8680bbc0e2ad1e4287aadd8489cf" +checksum = "aac423e5859d9f9ccdd32e3cf6a5866a15bedbf25aa6630bcb2acde9468f6ae3" dependencies = [ "base64 0.22.1", "brotli", @@ -4466,35 +4430,35 @@ dependencies = [ "semver", "serde", "serde_json", - "sha2 0.10.9", - "syn 2.0.114", + "sha2", + "syn 2.0.115", "tauri-utils", "thiserror 2.0.18", "time", "url", - "uuid 1.19.0", + "uuid 1.21.0", "walkdir", ] [[package]] name = "tauri-macros" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3764a12f886d8245e66b7ee9b43ccc47883399be2019a61d80cf0f4117446fde" +checksum = "1b6a1bd2861ff0c8766b1d38b32a6a410f6dc6532d4ef534c47cfb2236092f59" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "tauri-codegen", "tauri-utils", ] [[package]] name = "tauri-plugin" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1d0a4860b7ff570c891e1d2a586bf1ede205ff858fbc305e0b5ae5d14c1377" +checksum = "692a77abd8b8773e107a42ec0e05b767b8d2b7ece76ab36c6c3947e34df9f53f" dependencies = [ "anyhow", "glob", @@ -4509,9 +4473,9 @@ dependencies = [ [[package]] name = "tauri-plugin-deep-link" -version = "2.4.6" +version = "2.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444b091f24f2f6bdb4a305b54d3961f629c11861c685aceeea9a1972f89e43d5" +checksum = "94deb2e2e4641514ac496db2cddcfc850d6fc9d51ea17b82292a0490bd20ba5b" dependencies = [ "dunce", "plist", @@ -4611,9 +4575,9 @@ dependencies = [ [[package]] name = "tauri-plugin-single-instance" -version = "2.3.7" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acba6b5ca527a96cdfcc96ae09b09ccb91ddff5e33978ca6873b96ea16bb404c" +checksum = "dc61e4822b8f74d68278e09161d3e3fdd1b14b9eb781e24edccaabf10c420e8c" dependencies = [ "serde", "serde_json", @@ -4627,9 +4591,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f766fe9f3d1efc4b59b17e7a891ad5ed195fa8d23582abb02e6c9a01137892" +checksum = "b885ffeac82b00f1f6fd292b6e5aabfa7435d537cef57d11e38a489956535651" dependencies = [ "cookie", "dpi", @@ -4652,9 +4616,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.9.3" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187a3f26f681bdf028f796ccf57cf478c1ee422c50128e5a0a6ebeb3f5910065" +checksum = "5204682391625e867d16584fedc83fc292fb998814c9f7918605c789cd876314" dependencies = [ "gtk", "http", @@ -4679,9 +4643,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.8.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a423c51176eb3616ee9b516a9fa67fed5f0e78baaba680e44eb5dd2cc37490" +checksum = "fcd169fccdff05eff2c1033210b9b94acd07a47e6fa9a3431cf09cfd4f01c87e" dependencies = [ "anyhow", "brotli", @@ -4711,7 +4675,7 @@ dependencies = [ "toml 0.9.11+spec-1.1.0", "url", "urlpattern", - "uuid 1.19.0", + "uuid 1.21.0", "walkdir", ] @@ -4788,7 +4752,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -4799,14 +4763,14 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] name = "time" -version = "0.3.45" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", @@ -4820,15 +4784,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.25" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -4892,7 +4856,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -5035,7 +4999,7 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytes", "futures-util", "http", @@ -5078,7 +5042,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -5120,9 +5084,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typed-path" -version = "0.12.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7922f2cdc51280d47b491af9eafc41eb0cdab85eabcb390c854412fcbf26dbe8" +checksum = "3015e6ce46d5ad8751e4a772543a30c7511468070e98e64e20165f8f81155b64" [[package]] name = "typeid" @@ -5190,9 +5154,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" [[package]] name = "unicode-segmentation" @@ -5200,6 +5164,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "untrusted" version = "0.9.0" @@ -5254,11 +5224,11 @@ dependencies = [ [[package]] name = "uuid" -version = "1.19.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.1", "js-sys", "serde_core", "wasm-bindgen", @@ -5346,6 +5316,15 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasm-bindgen" version = "0.2.108" @@ -5392,7 +5371,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "wasm-bindgen-shared", ] @@ -5405,11 +5384,33 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.13.0", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm-streams" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" dependencies = [ "futures-util", "js-sys", @@ -5418,6 +5419,18 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "semver", +] + [[package]] name = "web-sys" version = "0.3.85" @@ -5440,9 +5453,9 @@ dependencies = [ [[package]] name = "webkit2gtk" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a" +checksum = "a1027150013530fb2eaf806408df88461ae4815a45c541c8975e61d6f2fc4793" dependencies = [ "bitflags 1.3.2", "cairo-rs", @@ -5464,9 +5477,9 @@ dependencies = [ [[package]] name = "webkit2gtk-sys" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c" +checksum = "916a5f65c2ef0dfe12fff695960a2ec3d4565359fdbb2e9943c974e06c734ea5" dependencies = [ "bitflags 1.3.2", "cairo-sys-rs", @@ -5484,9 +5497,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" dependencies = [ "rustls-pki-types", ] @@ -5513,7 +5526,7 @@ checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -5694,7 +5707,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -5705,7 +5718,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -6095,6 +6108,88 @@ name = "wit-bindgen" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.13.0", + "prettyplease", + "syn 2.0.115", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.115", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap 2.13.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "writeable" @@ -6104,9 +6199,9 @@ checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "wry" -version = "0.53.5" +version = "0.54.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728b7d4c8ec8d81cab295e0b5b8a4c263c0d41a785fb8f8c4df284e5411140a2" +checksum = "5ed1a195b0375491dd15a7066a10251be217ce743cf4bbbbdcf5391d6473bee0" dependencies = [ "base64 0.22.1", "block2", @@ -6133,7 +6228,7 @@ dependencies = [ "once_cell", "percent-encoding", "raw-window-handle", - "sha2 0.10.9", + "sha2", "soup3", "tao-macros", "thiserror 2.0.18", @@ -6187,7 +6282,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "synstructure", ] @@ -6218,7 +6313,7 @@ dependencies = [ "serde_repr", "tracing", "uds_windows", - "uuid 1.19.0", + "uuid 1.21.0", "windows-sys 0.61.2", "winnow 0.7.14", "zbus_macros", @@ -6235,7 +6330,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "zbus_names", "zvariant", "zvariant_utils", @@ -6254,22 +6349,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.33" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" +checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.33" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" +checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -6289,7 +6384,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "synstructure", ] @@ -6310,7 +6405,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] @@ -6343,14 +6438,14 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", ] [[package]] name = "zip" -version = "7.2.0" +version = "8.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42e33efc22a0650c311c2ef19115ce232583abbe80850bc8b66509ebef02de0" +checksum = "6e499faf5c6b97a0d086f4a8733de6d47aee2252b8127962439d8d4311a73f72" dependencies = [ "aes", "bzip2", @@ -6358,8 +6453,7 @@ dependencies = [ "crc32fast", "deflate64", "flate2", - "generic-array", - "getrandom 0.3.4", + "getrandom 0.4.1", "hmac", "indexmap 2.13.0", "lzma-rust2", @@ -6376,15 +6470,15 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.5.5" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" +checksum = "a7948af682ccbc3342b6e9420e8c51c1fe5d7bf7756002b4a3c6cabfe96a7e3c" [[package]] name = "zmij" -version = "1.0.15" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f63c051f4fe3c1509da62131a678643c5b6fbdc9273b2b79d4378ebda003d2" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" [[package]] name = "zopfli" @@ -6449,7 +6543,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.115", "zvariant_utils", ] @@ -6462,6 +6556,6 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.114", + "syn 2.0.115", "winnow 0.7.14", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index f01ce5e5..2051cbdf 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collapseloader" -version = "0.2.7" +version = "0.2.8" description = "CollapseLoader" authors = ["dest4590"] edition = "2021" @@ -11,39 +11,39 @@ name = "collapseloader_lib" crate-type = ["staticlib", "cdylib", "rlib"] [build-dependencies] -tauri-build = { version = "2.5.3", features = [] } +tauri-build = { version = "2.5.5", features = [] } [dependencies] -tauri = { version = "2.9.5", features = ["devtools"] } +tauri = { version = "2.10.2", features = ["devtools", "tray-icon"] } tauri-plugin-opener = "2.5.3" tauri-plugin-notification = "2.3.3" -tauri-plugin-deep-link = "2.4.6" -tauri-plugin-single-instance = { version = "2.3.7", features = ["deep-link"] } +tauri-plugin-deep-link = "2.4.7" +tauri-plugin-single-instance = { version = "2.4.0", features = ["deep-link"] } serde = { version = "1.0.228", features = ["derive"] } serde_json = "1.0.149" colored = "3.1.1" -rand = "0.9.2" -reqwest = { version = "0.13.1", features = ["blocking", "json", "stream"] } +rand = "0.10.0" +reqwest = { version = "0.13.2", features = ["blocking", "json", "stream"] } semver = "1.0.27" -zip = "7.2.0" +zip = "8.1.0" tokio = { version = "1.49.0", features = ["macros", "process"] } -opener = "0.8.3" -uuid = { version = "1.19.0", features = ["v4"] } +opener = "0.8.4" +uuid = { version = "1.21.0", features = ["v4"] } chrono = { version = "0.4.43", features = ["serde"] } paste = "1.0.15" open = "5.3.3" md5 = "0.8.0" -discord-rich-presence = "1.0.0" -futures-util = "0.3.31" +discord-rich-presence = "1.1.0" +futures-util = "0.3.32" base64 = "0.22.1" tauri-plugin-dialog = "2.6.0" dotenvy = "0.15.7" tauri-plugin-fs = "2.4.5" thiserror = "2.0.18" -native-dialog = "0.9.4" +native-dialog = "0.9.6" sysinfo = "0.37.2" -socket2 = "0.6.1" -sha2 = "0.11.0-rc.3" +socket2 = "0.6.2" +sha2 = "0.10.9" [target.'cfg(windows)'.dependencies] winreg = { version = "0.55.0" } diff --git a/src-tauri/build.rs b/src-tauri/build.rs index 98600f71..e495cb66 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -109,8 +109,12 @@ fn main() { let git_hash = execute_git_command(&["rev-parse", "HEAD"]).unwrap_or_else(|_| "unknown".into()); let git_branch = execute_git_command(&["rev-parse", "--abbrev-ref", "HEAD"]) .unwrap_or_else(|_| "unknown".into()); + let git_commit_body = execute_git_command(&["show", "-s", "--format=%B", "HEAD"]) + .unwrap_or_else(|_| "unknown".into()); + println!("cargo:rustc-env=GIT_HASH={git_hash}"); println!("cargo:rustc-env=GIT_BRANCH={git_branch}"); + println!("cargo:rustc-env=GIT_COMMIT_BODY={git_commit_body}"); info(&format!("Build kind: {build_kind}")); info(&format!("Profile: {profile}")); diff --git a/src-tauri/src/commands/clients.rs b/src-tauri/src/commands/clients.rs index 06decd67..a55905b6 100644 --- a/src-tauri/src/commands/clients.rs +++ b/src-tauri/src/commands/clients.rs @@ -3,15 +3,16 @@ use core::clients::{ client::{Client, CLIENT_LOGS}, manager::ClientManager, }; -use serde::de::DeserializeOwned; -use serde::Deserialize; -use tauri::{AppHandle, State}; +use tauri::{AppHandle, Manager, State}; use crate::core::{ - clients::custom_clients::CustomClient, - network::analytics::Analytics, - storage::{custom_clients::CustomClientUpdate, data::Data}, - utils::globals::{API_VERSION, SKIP_AGENT_OVERLAY_VERIFICATION}, + clients::client::ClientType, + network::servers::{ServerConnectivityStatus, SERVERS}, + utils::helpers::emit_to_main_window, +}; +use crate::core::{ + clients::custom_clients::CustomClient, storage::custom_clients::CustomClientUpdate, + utils::globals::SKIP_AGENT_OVERLAY_VERIFICATION, }; use crate::core::{ clients::{client::LaunchOptions, internal::agent_overlay::AgentOverlayManager}, @@ -21,14 +22,6 @@ use crate::core::{ storage::settings::SETTINGS, utils::{discord_rpc, hashing::calculate_md5_hash, logging}, }; -use crate::{ - commands::utils::get_api_url, - core::{ - clients::client::ClientType, - network::servers::{ServerConnectivityStatus, SERVERS}, - utils::helpers::emit_to_main_window, - }, -}; use crate::{ core::{self, storage::data::DATA}, log_debug, log_error, log_info, log_warn, @@ -74,13 +67,15 @@ pub async fn initialize_api(state: State<'_, AppState>) -> Result<(), String> { return Err("Fetched client list is empty".to_string()); } - let mut manager = state - .clients - .manager - .lock() - .map_err(|_| "Failed to lock state".to_string())?; + { + let mut manager = state + .clients + .manager + .lock() + .map_err(|_| "Failed to lock state".to_string())?; - manager.clients = clients; + manager.clients = clients; + } Ok(()) } @@ -112,39 +107,6 @@ pub fn get_clients(state: State<'_, AppState>) -> Vec { .unwrap_or_default() } -#[derive(Deserialize)] -struct ApiResponse { - success: bool, - data: T, - #[serde(default)] - error: Option, - #[serde(default)] - #[allow(dead_code)] - timestamp: Option, -} - -async fn extract_api_data(response: reqwest::Response) -> Result { - if !response.status().is_success() { - return Err(format!("API returned error: {}", response.status())); - } - - let ApiResponse { - success, - data, - error, - .. - } = response - .json::>() - .await - .map_err(|e| format!("Failed to parse API response: {e}"))?; - - if !success { - return Err(error.unwrap_or_else(|| "API returned unsuccessful response".to_string())); - } - - Ok(data) -} - #[tauri::command] pub async fn launch_client( id: u32, @@ -154,34 +116,7 @@ pub async fn launch_client( ) -> Result<(), String> { let client = get_client_by_id(id, &state.clients.manager)?; - let filename_for_if = if client.filename.contains("fabric/") { - client.filename.replace("fabric/", "") - } else if client.filename.contains("/fabric") { - client.filename.replace("/fabric", "") - } else { - client.filename.clone() - }; - - const MAIN_SEPARATOR: char = std::path::MAIN_SEPARATOR; - - let file_name = Data::get_filename(&client.filename); - let jar_path = match client.client_type { - ClientType::Default => { - DATA.get_local(&format!("{file_name}{MAIN_SEPARATOR}{}", client.filename)) - } - ClientType::Fabric => DATA.get_local(&format!( - "{file_name}{MAIN_SEPARATOR}mods{MAIN_SEPARATOR}{filename_for_if}" - )), - ClientType::Forge => { - let jar_basename = std::path::Path::new(&client.filename) - .file_name() - .and_then(|n| n.to_str()) - .unwrap_or(&client.filename); - DATA.get_local(&format!( - "{file_name}{MAIN_SEPARATOR}mods{MAIN_SEPARATOR}{jar_basename}" - )) - } - }; + let (_, jar_path) = client.get_launch_paths()?; if !jar_path.exists() { log_warn!( @@ -331,6 +266,17 @@ pub async fn launch_client( let options = LaunchOptions::new(app_handle.clone(), user_token.clone(), false); + let minimize_on_launch = { + let settings = SETTINGS.lock().unwrap(); + settings.minimize_to_tray_on_launch.value + }; + + if minimize_on_launch { + if let Some(window) = app_handle.get_webview_window("main") { + let _ = window.hide(); + } + } + client.run(options, state.clients.manager.clone()).await } @@ -397,7 +343,6 @@ pub async fn download_client_only( let requirements_download = client.download_requirements(&app_handle); - Analytics::send_client_download_analytics(id); log_debug!("Sent client download analytics for ID: {}", id); tokio::try_join!(client_download, requirements_download)?; @@ -561,38 +506,6 @@ pub async fn delete_client(id: u32, state: State<'_, AppState>) -> Result<(), St } } -#[tauri::command] -pub async fn get_client_details(client_id: u32) -> Result { - log_debug!("Fetching details for client ID: {}", client_id); - let api_url = get_api_url().await?; - let base = api_url.trim_end_matches('/').to_string(); - let url = format!("{base}/api/{API_VERSION}/clients/{client_id}/detailed"); - log_debug!("Requesting client details from URL: {}", url); - - let client = reqwest::Client::new(); - let response = client.get(&url).send().await.map_err(|e| { - log_error!("Failed to fetch client details from {}: {}", url, e); - format!("Failed to fetch client details: {e}") - })?; - - if !response.status().is_success() { - log_warn!( - "API returned non-success status ({}) for client details request to {}", - response.status(), - url - ); - return Err(format!("API returned error: {}", response.status())); - } - - let details: serde_json::Value = response.json().await.map_err(|e| { - log_error!("Failed to parse client details JSON: {}", e); - format!("Failed to parse client details: {e}") - })?; - - log_info!("Successfully fetched details for client ID: {}", client_id); - Ok(details) -} - #[tauri::command] pub fn increment_client_counter( id: u32, @@ -665,14 +578,17 @@ pub fn add_custom_client( filename: String, file_path: String, main_class: String, + java_path: Option, + java_args: Option, state: State<'_, AppState>, ) -> Result<(), String> { log_info!("Adding new custom client: '{}'", name); let mut manager = state.custom_clients.lock(); let path_buf = PathBuf::from(file_path); - - let custom_client = CustomClient::new(0, name, version, filename, path_buf, main_class); + let mut custom_client = CustomClient::new(0, name, version, filename, path_buf, main_class); + custom_client.java_path = java_path; + custom_client.java_args = java_args; log_debug!("New custom client details: {:?}", custom_client); manager.add_client(custom_client) @@ -692,6 +608,8 @@ pub fn update_custom_client( name: Option, version: Option, main_class: Option, + java_path: Option, + java_args: Option, state: State<'_, AppState>, ) -> Result<(), String> { log_info!("Updating custom client with ID: {}", id); @@ -701,6 +619,8 @@ pub fn update_custom_client( name, version, main_class, + java_path, + java_args, }; log_debug!("Applying updates to custom client ID {}: {:?}", id, updates); @@ -751,6 +671,17 @@ pub async fn launch_custom_client( let options = LaunchOptions::new(app_handle.clone(), user_token.clone(), true); + let minimize_on_launch = { + let settings = SETTINGS.lock().unwrap(); + settings.minimize_to_tray_on_launch.value + }; + + if minimize_on_launch { + if let Some(window) = app_handle.get_webview_window("main") { + let _ = window.hide(); + } + } + client.run(options, state.clients.manager.clone()).await } @@ -769,6 +700,85 @@ pub async fn get_running_custom_client_ids() -> Vec { }) } +#[tauri::command] +pub async fn install_mod_from_url( + id: u32, + url: String, + filename: String, + state: State<'_, AppState>, +) -> Result<(), String> { + log_info!( + "Installing mod for client {}: {} from {}", + id, + filename, + url + ); + + let client = get_client_by_id(id, &state.clients.manager)?; + + let mods_folder_relative = match client.client_type { + ClientType::Fabric | ClientType::Forge | ClientType::Default => { + let (folder, _) = client.get_launch_paths().map_err(|e| e.to_string())?; + let root = DATA.root_dir.lock().unwrap().clone(); + let relative = folder + .strip_prefix(&root) + .map_err(|_| "Client folder is outside of root directory".to_string())?; + relative.join("mods") + } + }; + + let mods_folder_str = mods_folder_relative + .to_str() + .ok_or_else(|| "Invalid mods folder path".to_string())?; + + DATA.download_to_folder(&url, mods_folder_str).await?; + + log_info!( + "Successfully installed mod: {} to {}", + filename, + mods_folder_str + ); + + Ok(()) +} + +#[tauri::command] +pub async fn list_installed_mods( + id: u32, + state: State<'_, AppState>, +) -> Result, String> { + let client = get_client_by_id(id, &state.clients.manager)?; + + let mods_folder = match client.client_type { + ClientType::Fabric | ClientType::Forge | ClientType::Default => { + let (folder, _) = client.get_launch_paths().map_err(|e| e.to_string())?; + folder.join("mods") + } + }; + + if !mods_folder.exists() { + return Ok(Vec::new()); + } + + let mut mods = Vec::new(); + let mut entries = tokio::fs::read_dir(mods_folder) + .await + .map_err(|e| format!("Failed to read mods directory: {}", e))?; + + while let Some(entry) = entries.next_entry().await.map_err(|e| e.to_string())? { + let path = entry.path(); + if path.is_file() { + if let Some(filename) = path.file_name().and_then(|n| n.to_str()) { + if filename.ends_with(".jar") { + mods.push(filename.to_string()); + } + } + } + } + + Ok(mods) +} + #[tauri::command] pub async fn stop_custom_client(id: u32, state: State<'_, AppState>) -> Result<(), String> { log_info!("Attempting to stop custom client with ID: {}", id); @@ -789,64 +799,3 @@ pub async fn stop_custom_client(id: u32, state: State<'_, AppState>) -> Result<( .await .map_err(|e| format!("Stop custom client task error: {e}"))? } - -#[tauri::command] -pub async fn get_client_comments(client_id: u32) -> Result { - log_debug!("Fetching comments for client ID: {}", client_id); - let api_url = get_api_url().await?; - let base = api_url.trim_end_matches('/').to_string(); - let url = format!("{base}/api/{API_VERSION}/clients/{client_id}/comments"); - - let client = reqwest::Client::new(); - let response = client.get(&url).send().await.map_err(|e| { - log_error!("Failed to fetch client comments from {}: {}", url, e); - format!("Failed to fetch client comments: {e}") - })?; - - extract_api_data(response).await -} - -#[tauri::command] -pub async fn add_client_comment( - client_id: u32, - content: String, - user_token: String, -) -> Result { - let api_url = get_api_url().await?; - let base = api_url.trim_end_matches('/').to_string(); - let url = format!("{base}/api/{API_VERSION}/clients/{client_id}/comments"); - - let client = reqwest::Client::new(); - let response = client - .post(&url) - .header("Authorization", format!("Bearer {}", user_token)) - .json(&serde_json::json!({ "content": content })) - .send() - .await - .map_err(|e| format!("Failed to add comment: {e}"))?; - - extract_api_data(response).await -} - -#[tauri::command] -pub async fn delete_client_comment( - client_id: u32, - comment_id: u32, - user_token: String, -) -> Result<(), String> { - let api_url = get_api_url().await?; - let base = api_url.trim_end_matches('/').to_string(); - let url = format!("{base}/api/{API_VERSION}/clients/{client_id}/comments/{comment_id}"); - - let client = reqwest::Client::new(); - let response = client - .delete(&url) - .header("Authorization", format!("Bearer {}", user_token)) - .send() - .await - .map_err(|e| format!("Failed to delete comment: {e}"))?; - - extract_api_data::(response) - .await - .map(|_| ()) -} diff --git a/src-tauri/src/commands/irc.rs b/src-tauri/src/commands/irc.rs index 52d609b5..5ca2581f 100644 --- a/src-tauri/src/commands/irc.rs +++ b/src-tauri/src/commands/irc.rs @@ -108,8 +108,10 @@ pub async fn connect_irc( Ok(0) => { log_info!("IRC connection closed by server"); app_clone.emit("irc-disconnected", ()).unwrap_or_default(); - let mut writer_guard = writer_for_reader.lock().await; - *writer_guard = None; + { + let mut writer_guard = writer_for_reader.lock().await; + *writer_guard = None; + } break; } Ok(_) => { @@ -123,8 +125,10 @@ pub async fn connect_irc( .emit("irc-error", e.to_string()) .unwrap_or_default(); app_clone.emit("irc-disconnected", ()).unwrap_or_default(); - let mut writer_guard = writer_for_reader.lock().await; - *writer_guard = None; + { + let mut writer_guard = writer_for_reader.lock().await; + *writer_guard = None; + } break; } } @@ -142,8 +146,8 @@ pub async fn connect_irc( #[tauri::command] pub async fn disconnect_irc(state: State<'_, IrcState>) -> Result<(), String> { - let mut writer = state.writer.lock().await; - if let Some(mut w) = writer.take() { + let value = state.writer.lock().await.take(); + if let Some(mut w) = value { let _ = w.shutdown().await; } Ok(()) diff --git a/src-tauri/src/commands/presets.rs b/src-tauri/src/commands/presets.rs index 4fb2c75f..c61d6463 100644 --- a/src-tauri/src/commands/presets.rs +++ b/src-tauri/src/commands/presets.rs @@ -8,7 +8,9 @@ use uuid::Uuid; pub struct CreatePresetInput { pub name: String, pub description: Option, + #[serde(rename = "customCSS", alias = "customCss")] pub custom_css: String, + #[serde(rename = "enableCustomCSS", alias = "enableCustomCss")] pub enable_custom_css: bool, // daisyui @@ -33,6 +35,13 @@ pub struct CreatePresetInput { pub warning_content: Option, pub error: Option, pub error_content: Option, + + #[serde(rename = "backgroundImage")] + pub background_image: Option, + #[serde(rename = "backgroundBlur")] + pub background_blur: Option, + #[serde(rename = "backgroundOpacity")] + pub background_opacity: Option, } #[derive(serde::Deserialize)] @@ -41,7 +50,9 @@ pub struct UpdatePresetInput { pub id: String, pub name: String, pub description: Option, + #[serde(rename = "customCSS", alias = "customCss")] pub custom_css: String, + #[serde(rename = "enableCustomCSS", alias = "enableCustomCss")] pub enable_custom_css: bool, // daisyui @@ -66,6 +77,13 @@ pub struct UpdatePresetInput { pub warning_content: Option, pub error: Option, pub error_content: Option, + + #[serde(rename = "backgroundImage")] + pub background_image: Option, + #[serde(rename = "backgroundBlur")] + pub background_blur: Option, + #[serde(rename = "backgroundOpacity")] + pub background_opacity: Option, } #[tauri::command] @@ -121,6 +139,10 @@ pub fn create_preset(input: CreatePresetInput) -> Result { warning_content: input.warning_content, error: input.error, error_content: input.error_content, + + background_image: input.background_image, + background_blur: input.background_blur, + background_opacity: input.background_opacity, }; preset_manager.add_preset(preset.clone())?; @@ -174,6 +196,10 @@ pub fn update_preset(input: UpdatePresetInput) -> Result { warning_content: input.warning_content, error: input.error, error_content: input.error_content, + + background_image: input.background_image, + background_blur: input.background_blur, + background_opacity: input.background_opacity, }; preset_manager.update_preset(preset.clone())?; @@ -228,6 +254,10 @@ pub fn duplicate_preset(id: String, new_name: String) -> Result Result<(), String> { #[cfg(target_os = "windows")] let new_dpi_bypass_value = input_settings.dpi_bypass.value; - let input_settings_clone = input_settings.clone(); - let new_settings = Settings::from_input(input_settings_clone, config_path); + let new_settings = Settings::from_input(input_settings, config_path); *current_settings = new_settings.clone(); new_settings.save_to_disk(); @@ -66,11 +65,15 @@ pub fn save_settings(input_settings: InputSettings) -> Result<(), String> { #[cfg(target_os = "windows")] { - if dpi_bypass_changed && new_dpi_bypass_value { - log_info!("DPI bypass enabled. Preparing to download and run package"); - - if let Err(e) = dpi::download_dpi_bypass() { - log_error!("Failed to initiate DPI bypass setup: {e}"); + if dpi_bypass_changed { + if new_dpi_bypass_value { + log_info!("DPI bypass enabled. Preparing to download and run package"); + if let Err(e) = dpi::enable_dpi_bypass_async() { + log_error!("Failed to initiate DPI bypass setup: {e}"); + } + } else { + log_info!("DPI bypass disabled. Killing existing processes"); + dpi::kill_winws(); } } } @@ -323,7 +326,6 @@ pub fn is_telemetry_consent_shown() -> Result { #[tauri::command] pub fn set_custom_clients_display(display: String) -> Result<(), String> { - log_info!("Setting custom clients display to: {}", display); let mut flags = FLAGS_MANAGER.lock().unwrap(); flags.set_custom_clients_display(display); flags.save_to_disk(); diff --git a/src-tauri/src/commands/updater.rs b/src-tauri/src/commands/updater.rs index c3c2facf..ff12e06b 100644 --- a/src-tauri/src/commands/updater.rs +++ b/src-tauri/src/commands/updater.rs @@ -374,7 +374,7 @@ exit } #[tauri::command] -pub const fn get_changelog() -> Vec { +pub fn get_changelog() -> Vec { Vec::new() } diff --git a/src-tauri/src/commands/utils.rs b/src-tauri/src/commands/utils.rs index d3029161..f5f14c4c 100644 --- a/src-tauri/src/commands/utils.rs +++ b/src-tauri/src/commands/utils.rs @@ -3,8 +3,14 @@ use base64::{engine::general_purpose, Engine}; use crate::commands::clients::{ get_running_client_ids, get_running_custom_client_ids, stop_client, stop_custom_client, }; +use crate::core::storage::accounts::ACCOUNT_MANAGER; +use crate::core::storage::custom_clients::CUSTOM_CLIENT_MANAGER; +use crate::core::storage::favorites::FAVORITE_MANAGER; +use crate::core::storage::flags::FLAGS_MANAGER; +use crate::core::storage::presets::PRESET_MANAGER; +use crate::core::storage::settings::SETTINGS; use crate::core::utils::discord_rpc; -use crate::core::utils::globals::{API_VERSION, CODENAME}; +use crate::core::utils::globals::{API_VERSION, CDN_SERVERS, CODENAME}; use crate::core::utils::helpers::is_development_enabled; use crate::core::{network::servers::SERVERS, storage::data::DATA}; use crate::AppState; @@ -19,6 +25,7 @@ pub fn get_version() -> Result { "version": env!("CARGO_PKG_VERSION").to_string(), "codename": CODENAME, "commitHash": env!("GIT_HASH").to_string(), + "commitMessage": env!("GIT_COMMIT_BODY").to_string(), "branch": env!("GIT_BRANCH").to_string(), "development": env!("DEVELOPMENT").to_lowercase(), }); @@ -33,7 +40,7 @@ pub fn is_development() -> Result { #[tauri::command] pub fn open_data_folder() -> Result { - let path = DATA.root_dir.to_string_lossy().to_string(); + let path = DATA.root_dir.lock().unwrap().to_string_lossy().to_string(); log_info!("Opening data folder at: {}", path); if let Err(e) = open::that(&path) { @@ -57,7 +64,7 @@ pub async fn reset_requirements() -> Result<(), String> { #[tauri::command] pub fn get_data_folder() -> Result { - let path = DATA.root_dir.to_string_lossy().to_string(); + let path = DATA.root_dir.lock().unwrap().to_string_lossy().to_string(); log_debug!("Getting data folder path: {}", path); Ok(path) } @@ -92,9 +99,9 @@ pub async fn change_data_folder( } log_info!("Stopping all running clients before changing data folder"); - let running: Vec = get_running_client_ids(state.clone()) - .await - .map_err(|e| e.to_string())?; + + let running: Vec = get_running_client_ids(state.clone()).await?; + for id in running { log_debug!("Stopping client with ID: {}", id); let _ = stop_client(id, state.clone()).await; @@ -106,7 +113,7 @@ pub async fn change_data_folder( let _ = stop_custom_client(id, state.clone()).await; } - let current_dir = DATA.root_dir.clone(); + let current_dir = DATA.root_dir.lock().unwrap().clone(); log_debug!("Current data directory is: {:?}", current_dir); if mode == "move" { @@ -121,6 +128,13 @@ pub async fn change_data_folder( let entry = entry.map_err(|e| e.to_string())?; let path = entry.path(); let target = dst.join(entry.file_name()); + + let file_type = entry.file_type().map_err(|e| e.to_string())?; + if file_type.is_symlink() { + log_debug!("Skipping symlink during move: {:?}", path); + continue; + } + if path.is_dir() { fs::create_dir_all(&target).map_err(|e| e.to_string())?; copy_dir_recursive(&path, &target)?; @@ -170,10 +184,45 @@ pub async fn change_data_folder( override_file ); fs::write(&override_file, &new_path).map_err(|e| { - log_error!("Failed to write override file: {}", e); - format!("Failed to write override: {e}") + log_error!("Failed to write to override file: {:?}", e); + format!("Failed to write to override file: {e}") })?; + { + let mut root = DATA.root_dir.lock().unwrap(); + *root = PathBuf::from(new_path.clone()); + } + + let new_root = PathBuf::from(new_path.clone()); + + if let Ok(mut s) = SETTINGS.lock() { + s.config_path = new_root.join("config.json"); + log_debug!("Updated SETTINGS path: {:?}", s.config_path); + } + if let Ok(mut pm) = PRESET_MANAGER.lock() { + pm.config_path = new_root.join("presets.json"); + log_debug!("Updated PRESET_MANAGER path: {:?}", pm.config_path); + } + if let Ok(mut am) = ACCOUNT_MANAGER.lock() { + am.accounts_path = new_root.join("accounts.json"); + log_debug!("Updated ACCOUNT_MANAGER path: {:?}", am.accounts_path); + } + if let Ok(mut ccm) = CUSTOM_CLIENT_MANAGER.lock() { + ccm.custom_clients_path = new_root.join("custom_clients.json"); + log_debug!( + "Updated CUSTOM_CLIENT_MANAGER path: {:?}", + ccm.custom_clients_path + ); + } + if let Ok(mut fm) = FAVORITE_MANAGER.lock() { + fm.favorites_path = new_root.join("favorites.json"); + log_debug!("Updated FAVORITE_MANAGER path: {:?}", fm.favorites_path); + } + if let Ok(mut f) = FLAGS_MANAGER.lock() { + f.flags_path = new_root.join("flags.json"); + log_debug!("Updated FLAGS_MANAGER path: {:?}", f.flags_path); + } + if let Some(window) = app.get_webview_window("main") { log_debug!("Emitting 'data-folder-changed' event to main window"); let _ = window.emit("data-folder-changed", &new_path); @@ -190,6 +239,19 @@ pub async fn get_api_url() -> Result { .map_or_else(|| Ok("https://atlas.collapseloader.org".to_string()), Ok) } +#[tauri::command] +pub async fn get_cdn_url() -> Result { + SERVERS.get_cdn_server_url().map_or_else( + || { + Ok(CDN_SERVERS + .first() + .map(|s| s.url.clone()) + .unwrap_or_default()) + }, + Ok, + ) +} + #[tauri::command] pub fn get_api_version() -> Result { Ok(API_VERSION.to_string()) diff --git a/src-tauri/src/core/clients/client.rs b/src-tauri/src/core/clients/client.rs index fd9c9a26..6cee6716 100644 --- a/src-tauri/src/core/clients/client.rs +++ b/src-tauri/src/core/clients/client.rs @@ -23,10 +23,10 @@ use crate::core::storage::{ use crate::core::utils::{ globals::{ AGENT_FILE, AGENT_OVERLAY_FOLDER, ASSETS_FABRIC_FOLDER, ASSETS_FABRIC_ZIP, ASSETS_FOLDER, - ASSETS_ZIP, CUSTOM_CLIENTS_FOLDER, FILE_EXTENSION, IS_LINUX, JDK21_FOLDER, JDK8_FOLDER, - JDK8_ZIP, LEGACY_SUFFIX, LIBRARIES_FABRIC_FOLDER, LIBRARIES_FOLDER, - LIBRARIES_LEGACY_FOLDER, LIBRARIES_LEGACY_ZIP, LIBRARIES_ZIP, LINUX_SUFFIX, - MINECRAFT_VERSIONS_FOLDER, MODS_FOLDER, NATIVES_FOLDER, NATIVES_LEGACY_ZIP, + ASSETS_ZIP, CUSTOM_CLIENTS_FOLDER, FABRIC_DEPS_URL, FILE_EXTENSION, FORGE_DEPS_URL, + IS_LINUX, JDK21_FOLDER, JDK8_FOLDER, LEGACY_SUFFIX, LIBRARIES_FABRIC_FOLDER, + LIBRARIES_FOLDER, LIBRARIES_LEGACY_FOLDER, LIBRARIES_LEGACY_ZIP, LIBRARIES_ZIP, + LINUX_SUFFIX, MINECRAFT_VERSIONS_FOLDER, MODS_FOLDER, NATIVES_FOLDER, NATIVES_LEGACY_ZIP, NATIVES_LINUX_ZIP, NATIVES_ZIP, PATH_SEPARATOR, }, hashing::calculate_md5_hash, @@ -70,12 +70,6 @@ fn is_minecraft_version_dir_name(name: &str) -> bool { .all(|p| !p.is_empty() && p.chars().all(|c| c.is_ascii_digit())) } -fn is_fabric_loader_jar(path: &Path) -> bool { - path.file_name() - .and_then(|n| n.to_str()) - .is_some_and(|n| n.starts_with("fabric-loader") && n.ends_with(".jar")) -} - fn collect_jars_recursive(dir: &Path, skip_root_mc_version_dirs: bool) -> Vec { let mut jars = Vec::new(); @@ -159,6 +153,8 @@ impl Meta { .and_then(|n| n.to_str()) .unwrap_or(filename); DATA.root_dir + .lock() + .unwrap() .join(Data::get_filename(filename)) .join(MODS_FOLDER) .join(jar_basename) @@ -170,6 +166,8 @@ impl Meta { .and_then(|n| n.to_str()) .unwrap_or(filename); DATA.root_dir + .lock() + .unwrap() .join(Data::get_filename(filename)) .join(MODS_FOLDER) .join(jar_basename) @@ -235,6 +233,10 @@ pub struct Client { pub client_type: ClientType, #[serde(default = "default_created_at")] pub created_at: DateTime, + #[serde(default)] + pub java_path: Option, + #[serde(default)] + pub java_args: Option, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] @@ -244,7 +246,7 @@ pub struct Requirement { size: Option, } -const fn default_meta() -> Meta { +fn default_meta() -> Meta { Meta { is_new: false, is_fabric: false, @@ -267,7 +269,7 @@ pub struct LaunchOptions { } impl LaunchOptions { - pub const fn new(app_handle: AppHandle, user_token: String, is_custom: bool) -> Self { + pub fn new(app_handle: AppHandle, user_token: String, is_custom: bool) -> Self { Self { app_handle, user_token, @@ -292,28 +294,35 @@ impl Client { fn jdk_zip_name(&self) -> String { if self.client_type == ClientType::Forge { - JDK8_ZIP.to_string() + format!("misc/{JDK8_FOLDER}.zip") } else { - format!("{JDK21_FOLDER}.zip") + format!("misc/{JDK21_FOLDER}.zip") } } fn java_executable_path(&self) -> PathBuf { DATA.root_dir + .lock() + .unwrap() .join(self.jdk_folder_name()) .join("bin") .join(format!("java{FILE_EXTENSION}")) } - fn get_launch_paths(&self) -> Result<(PathBuf, PathBuf), String> { + pub fn get_launch_paths(&self) -> Result<(PathBuf, PathBuf), String> { if self.meta.is_custom { - let folder = DATA.root_dir.join(CUSTOM_CLIENTS_FOLDER).join(&self.name); + let folder = DATA + .root_dir + .lock() + .unwrap() + .join(CUSTOM_CLIENTS_FOLDER) + .join(&self.name); let jar = folder.join(&self.filename); return Ok((folder, jar)); } let base_name = Data::get_filename(&self.filename); - let folder = DATA.root_dir.join(&base_name); + let folder = DATA.root_dir.lock().unwrap().join(&base_name); match self.client_type { ClientType::Forge | ClientType::Fabric => { @@ -324,11 +333,14 @@ impl Client { Ok((folder.clone(), folder.join(MODS_FOLDER).join(jar_basename))) } ClientType::Default => { + let jar_basename = Path::new(&self.filename) + .file_name() + .and_then(|n| n.to_str()) + .unwrap_or(&self.filename); if self.filename.contains("fabric/") { - let jar_basename = Path::new(&self.filename).file_name().unwrap(); Ok((folder.clone(), folder.join(MODS_FOLDER).join(jar_basename))) } else { - Ok((folder.clone(), folder.join(&self.filename))) + Ok((folder.clone(), folder.join(jar_basename))) } } } @@ -339,10 +351,14 @@ impl Client { match self.client_type { ClientType::Fabric => DATA .root_dir + .lock() + .unwrap() .join(MINECRAFT_VERSIONS_FOLDER) .join(format!("fabric_{}.jar", safe_ver)), ClientType::Forge => DATA .root_dir + .lock() + .unwrap() .join(MINECRAFT_VERSIONS_FOLDER) .join(format!("forge_{}.jar", safe_ver)), ClientType::Default => self.get_launch_paths().unwrap_or_default().1, @@ -380,9 +396,17 @@ impl Client { let client_base = Data::get_filename(&self.filename); let mods_folder = format!("{client_base}{MAIN_SEPARATOR}{MODS_FOLDER}"); let safe_ver = sanitize_version_for_paths(&self.version); - let forge_jar_name = format!("forge_{}.jar", safe_ver); + let forge_jar_name = + format!("misc/{MINECRAFT_VERSIONS_FOLDER}/forge_{}.jar", safe_ver); - DATA.download_to_folder(&self.filename, &mods_folder) + let remote_path = if self.filename.contains('/') { + let parts: Vec<&str> = self.filename.split('/').collect(); + format!("clients/{}/jars/{}", parts[0], parts[1]) + } else { + format!("clients/forge/jars/{}", self.filename) + }; + + DATA.download_to_folder(&remote_path, &mods_folder) .await .map_err(|e| format!("Forge Mod download failed: {e}"))?; @@ -390,7 +414,26 @@ impl Client { .await .map_err(|e| format!("Forge MC Jar download failed: {e}")) } - _ => DATA.download(&self.filename).await, + ClientType::Fabric => { + let client_base = Data::get_filename(&self.filename); + let mods_folder = format!("{client_base}{MAIN_SEPARATOR}{MODS_FOLDER}"); + let remote_path = if self.filename.contains('/') { + let parts: Vec<&str> = self.filename.split('/').collect(); + format!("clients/{}/jars/{}", parts[0], parts[1]) + } else { + format!("clients/fabric/jars/{}", self.filename) + }; + DATA.download_to_folder(&remote_path, &mods_folder).await + } + _ => { + let remote_path = if self.filename.contains('/') { + let parts: Vec<&str> = self.filename.split('/').collect(); + format!("clients/{}/jars/{}", parts[0], parts[1]) + } else { + format!("clients/vanilla/jars/{}", self.filename) + }; + DATA.download(&remote_path).await + } }; if let Err(e) = download_result { @@ -409,14 +452,7 @@ impl Client { return Err(e); } - ClientManager::get_client(manager, self.id, |c| { - c.meta.installed = true; - c.meta.size = self.size; - }); - log_debug!( - "Client '{}' downloaded and installed successfully", - self.name - ); + log_debug!("Client '{}' download procedure finished", self.name); Ok(()) } @@ -472,6 +508,76 @@ impl Client { Ok(()) } + async fn download_dependency( + &self, + remote_path: &str, + local_folder_rel: &str, + local_file_abs: &Path, + expected_md5: Option<&String>, + name_for_logs: &str, + ) -> Result<(), String> { + let mut need_download = true; + + if local_file_abs.exists() { + if let Some(expected) = expected_md5 { + let ok = Data::verify_file_md5(local_file_abs, expected) + .await + .map_err(|e| format!("Failed to verify MD5 for {name_for_logs}: {e}"))?; + if ok { + need_download = false; + } else { + log_warn!( + "MD5 mismatch for {}. Expected: {}. Redownloading...", + name_for_logs, + expected + ); + let _ = std::fs::remove_file(local_file_abs); + need_download = true; + } + } else { + need_download = false; + } + } + + if need_download { + log_info!("Downloading dependency: {}", remote_path); + DATA.download_to_folder(remote_path, local_folder_rel) + .await + .map_err(|e| format!("Failed to download dependency {name_for_logs}: {e}"))?; + + if let Some(expected) = expected_md5 { + let ok = Data::verify_file_md5(local_file_abs, expected) + .await + .map_err(|e| format!("Failed to verify MD5 for {name_for_logs}: {e}"))?; + if !ok { + log_warn!( + "MD5 mismatch after download for {}. Retrying...", + name_for_logs + ); + let _ = std::fs::remove_file(local_file_abs); + DATA.download_to_folder(remote_path, local_folder_rel) + .await + .map_err(|e| { + format!("Failed to redownload dependency {name_for_logs}: {e}") + })?; + + let ok2 = Data::verify_file_md5(local_file_abs, expected) + .await + .map_err(|e| { + format!("Failed to verify MD5 for {name_for_logs} after retry: {e}") + })?; + if !ok2 { + let _ = std::fs::remove_file(local_file_abs); + return Err(format!( + "MD5 mismatch for {name_for_logs} after retry. Aborting." + )); + } + } + } + } + Ok(()) + } + async fn download_fabric_mods(&self) -> Result<(), String> { if self.client_type != ClientType::Fabric { return Ok(()); @@ -480,77 +586,61 @@ impl Client { if let Some(mods) = &self.dependencies { let client_base = Data::get_filename(&self.filename); let mods_folder_rel = format!("{client_base}{MAIN_SEPARATOR}{MODS_FOLDER}"); - let mods_folder_abs = DATA.root_dir.join(&client_base).join(MODS_FOLDER); + let mods_folder_abs = DATA + .root_dir + .lock() + .unwrap() + .join(&client_base) + .join(MODS_FOLDER); for req in mods { let name = req.name.clone(); - let expected_md5 = req.md5_hash.clone(); - let mod_basename = name.trim_end_matches(".jar"); let dest = mods_folder_abs.join(format!("{mod_basename}.jar")); - let remote_path = format!("fabric/deps/{mod_basename}.jar"); - - let mut need_download = true; - if dest.exists() { - if let Some(ref expected) = expected_md5 { - let ok = Data::verify_file_md5(&dest, expected) - .await - .map_err(|e| format!("Failed to verify MD5 for {mod_basename}: {e}"))?; - if ok { - need_download = false; - } else { - log_warn!( - "MD5 mismatch for {}. Expected: {}. Redownloading...", - mod_basename, - expected - ); - let _ = std::fs::remove_file(&dest); - need_download = true; - } - } else { - need_download = false; - } - } + let remote_path = format!("{FABRIC_DEPS_URL}/{mod_basename}.jar"); + + self.download_dependency( + &remote_path, + &mods_folder_rel, + &dest, + req.md5_hash.as_ref(), + mod_basename, + ) + .await?; + } + } + Ok(()) + } - if need_download { - log_info!("Downloading dependency: {}", remote_path); - DATA.download_to_folder(&remote_path, &mods_folder_rel) - .await - .map_err(|e| { - format!("Failed to download dependency {mod_basename}: {e}") - })?; + async fn download_forge_mods(&self) -> Result<(), String> { + if self.client_type != ClientType::Forge { + return Ok(()); + } - if let Some(ref expected) = expected_md5 { - let ok = Data::verify_file_md5(&dest, expected) - .await - .map_err(|e| format!("Failed to verify MD5 for {mod_basename}: {e}"))?; - if !ok { - log_warn!( - "MD5 mismatch after download for {}. Retrying...", - mod_basename - ); - let _ = std::fs::remove_file(&dest); - DATA.download_to_folder(&remote_path, &mods_folder_rel) - .await - .map_err(|e| { - format!("Failed to redownload dependency {mod_basename}: {e}") - })?; - - let ok2 = - Data::verify_file_md5(&dest, expected).await.map_err(|e| { - format!( - "Failed to verify MD5 for {mod_basename} after retry: {e}" - ) - })?; - if !ok2 { - let _ = std::fs::remove_file(&dest); - return Err(format!( - "MD5 mismatch for {mod_basename} after retry. Aborting." - )); - } - } - } - } + if let Some(mods) = &self.dependencies { + let client_base = Data::get_filename(&self.filename); + let mods_folder_rel = format!("{client_base}{MAIN_SEPARATOR}{MODS_FOLDER}"); + let mods_folder_abs = DATA + .root_dir + .lock() + .unwrap() + .join(&client_base) + .join(MODS_FOLDER); + + for req in mods { + let name = req.name.clone(); + let mod_basename = name.trim_end_matches(".jar"); + let dest = mods_folder_abs.join(format!("{mod_basename}.jar")); + let remote_path = format!("{FORGE_DEPS_URL}/{mod_basename}.jar"); + + self.download_dependency( + &remote_path, + &mods_folder_rel, + &dest, + req.md5_hash.as_ref(), + mod_basename, + ) + .await?; } } Ok(()) @@ -570,7 +660,7 @@ impl Client { || folder == JDK8_FOLDER || folder == JDK21_FOLDER { - let path = DATA.root_dir.join(folder); + let path = DATA.root_dir.lock().unwrap().join(folder); if !path.exists() { log_info!("Folder '{}' missing. Queuing {} for download.", folder, zip); files_to_download.push(zip.to_string()); @@ -583,7 +673,7 @@ impl Client { "Integrity check failed for '{}'. Wiping folder for clean redownload.", folder ); - let path = DATA.root_dir.join(folder); + let path = DATA.root_dir.lock().unwrap().join(folder); if path.exists() { let _ = std::fs::remove_dir_all(&path); } @@ -592,41 +682,43 @@ impl Client { }; check_and_queue(self.jdk_folder_name(), &self.jdk_zip_name()); + check_and_queue( + if self.client_type == ClientType::Fabric { + ASSETS_FABRIC_FOLDER + } else { + ASSETS_FOLDER + }, + if self.client_type == ClientType::Fabric { + ASSETS_FABRIC_ZIP + } else { + ASSETS_ZIP + }, + ); - match self.client_type { - ClientType::Fabric => { - check_and_queue(ASSETS_FABRIC_FOLDER, ASSETS_FABRIC_ZIP); - } - _ => { - check_and_queue(ASSETS_FOLDER, ASSETS_ZIP); - - let (libs_zip, libs_folder, natives_zip, natives_folder) = - if self.is_legacy_client() { - ( - LIBRARIES_LEGACY_ZIP, - LIBRARIES_LEGACY_FOLDER, - NATIVES_LEGACY_ZIP, - NATIVES_LEGACY_FOLDER, - ) - } else { - (LIBRARIES_ZIP, LIBRARIES_FOLDER, NATIVES_ZIP, NATIVES_FOLDER) - }; - - check_and_queue(libs_folder, libs_zip); - - let (actual_natives_zip, actual_natives_folder) = if IS_LINUX { - if self.is_legacy_client() { - (NATIVES_LEGACY_LINUX_ZIP, NATIVES_LEGACY_LINUX_FOLDER) - } else { - (NATIVES_LINUX_ZIP, NATIVES_LINUX_FOLDER) - } - } else { - (natives_zip, natives_folder) - }; + let (libs_zip, libs_folder, natives_zip, natives_folder) = if self.is_legacy_client() { + ( + LIBRARIES_LEGACY_ZIP, + LIBRARIES_LEGACY_FOLDER, + NATIVES_LEGACY_ZIP, + NATIVES_LEGACY_FOLDER, + ) + } else { + (LIBRARIES_ZIP, LIBRARIES_FOLDER, NATIVES_ZIP, NATIVES_FOLDER) + }; + + check_and_queue(libs_folder, libs_zip); - check_and_queue(actual_natives_folder, actual_natives_zip); + let (actual_natives_zip, actual_natives_folder) = if IS_LINUX { + if self.is_legacy_client() { + (NATIVES_LEGACY_LINUX_ZIP, NATIVES_LEGACY_LINUX_FOLDER) + } else { + (NATIVES_LINUX_ZIP, NATIVES_LINUX_FOLDER) } - } + } else { + (natives_zip, natives_folder) + }; + + check_and_queue(actual_natives_folder, actual_natives_zip); if !files_to_download.is_empty() { self.batch_download_requirements(app_handle, files_to_download) @@ -638,13 +730,18 @@ impl Client { } if self.client_type == ClientType::Fabric || self.client_type == ClientType::Forge { - let safe_ver = sanitize_version_for_paths(&self.version); let remote = match self.client_type { ClientType::Fabric => { - format!("fabric_{}.jar", safe_ver) + format!( + "misc/{MINECRAFT_VERSIONS_FOLDER}/fabric_{}.jar", + self.version + ) } ClientType::Forge => { - format!("forge_{}.jar", safe_ver) + format!( + "misc/{MINECRAFT_VERSIONS_FOLDER}/forge_{}.jar", + self.version + ) } _ => unreachable!(), }; @@ -652,24 +749,29 @@ impl Client { let dest_filename = remote.rsplit('/').next().unwrap_or(&remote); let local_path = DATA .root_dir + .lock() + .unwrap() .join(MINECRAFT_VERSIONS_FOLDER) .join(dest_filename); - if !local_path.exists() { - log_info!( - "MC jar missing, downloading: {} -> {}", - remote, - local_path.display() - ); - DATA.download_to_folder(&remote, MINECRAFT_VERSIONS_FOLDER) - .await?; - } + self.download_dependency( + &remote, + MINECRAFT_VERSIONS_FOLDER, + &local_path, + None, + dest_filename, + ) + .await?; } if self.client_type == ClientType::Fabric { self.download_fabric_mods().await?; } + if self.client_type == ClientType::Forge { + self.download_forge_mods().await?; + } + Ok(()) } @@ -696,6 +798,7 @@ impl Client { } self.download_fabric_mods().await?; + self.download_forge_mods().await?; tokio::time::sleep(tokio::time::Duration::from_millis(500)).await; @@ -712,7 +815,12 @@ impl Client { #[cfg(unix)] { use std::os::unix::fs::PermissionsExt; - let bin_dir = DATA.root_dir.join(self.jdk_folder_name()).join("bin"); + let bin_dir = DATA + .root_dir + .lock() + .unwrap() + .join(self.jdk_folder_name()) + .join("bin"); if bin_dir.exists() { if let Ok(entries) = std::fs::read_dir(&bin_dir) { for entry in entries.flatten() { @@ -739,18 +847,25 @@ impl Client { } async fn ensure_fabric_libraries(&self) -> Result<(), String> { - let common_dir = DATA.root_dir.join(LIBRARIES_FABRIC_FOLDER); + let common_dir = DATA.root_dir.lock().unwrap().join(LIBRARIES_FABRIC_FOLDER); + if !dir_has_any_jars(&common_dir, true) { log_info!("Downloading common Fabric libraries"); DATA.download(LIBRARIES_FABRIC_ZIP).await?; } let versioned_zip = format!( - "{}/{}.zip", + "misc/{}/{}.zip", LIBRARIES_FABRIC_FOLDER, sanitize_version_for_paths(&self.version) ); - let versioned_dir = DATA.root_dir.join(versioned_zip.replace(".zip", "")); + + let versioned_dir = DATA.root_dir.lock().unwrap().join( + versioned_zip + .strip_prefix("misc/") + .unwrap_or(&versioned_zip) + .replace(".zip", ""), + ); if !dir_has_any_jars(&versioned_dir, false) { log_info!("Downloading versioned Fabric libraries: {}", versioned_zip); @@ -766,8 +881,10 @@ impl Client { log_warn!("Java executable missing. Redownloading requirements..."); - let _ = tokio::fs::remove_dir_all(DATA.root_dir.join(self.jdk_folder_name())).await; - let _ = tokio::fs::remove_file(DATA.root_dir.join(self.jdk_zip_name())).await; + let jdk_dir = DATA.root_dir.lock().unwrap().join(self.jdk_folder_name()); + let _ = tokio::fs::remove_dir_all(jdk_dir).await; + let jdk_zip = DATA.root_dir.lock().unwrap().join(self.jdk_zip_name()); + let _ = tokio::fs::remove_file(jdk_zip).await; self.download_requirements(app_handle).await?; @@ -779,7 +896,7 @@ impl Client { fn build_classpath(&self) -> Result { let (_, client_jar) = self.get_launch_paths()?; - let agent_overlay = DATA.root_dir.join(AGENT_OVERLAY_FOLDER); + let agent_overlay = DATA.root_dir.lock().unwrap().join(AGENT_OVERLAY_FOLDER); let mut cp_parts = Vec::new(); @@ -789,27 +906,25 @@ impl Client { let v_libs = DATA .root_dir + .lock() + .unwrap() .join(LIBRARIES_FABRIC_FOLDER) - .join(sanitize_version_for_paths(&self.version)); + .join(format!("{}", sanitize_version_for_paths(&self.version))); cp_parts.extend(collect_jars_recursive(&v_libs, false)); - let g_libs = DATA.root_dir.join(LIBRARIES_FABRIC_FOLDER); - for jar in collect_jars_recursive(&g_libs, true) { - if !is_fabric_loader_jar(&jar) { - cp_parts.push(jar); - } - } + let g_libs = DATA.root_dir.lock().unwrap().join(LIBRARIES_FABRIC_FOLDER); + cp_parts.extend(collect_jars_recursive(&g_libs, true)); } ClientType::Forge => { cp_parts.push(self.get_minecraft_jar_path()); - let libs = DATA.root_dir.join(LIBRARIES_LEGACY_FOLDER); + let libs = DATA.root_dir.lock().unwrap().join(LIBRARIES_LEGACY_FOLDER); cp_parts.extend(collect_jars_recursive(&libs, false)); } ClientType::Default => { let libs = if self.is_legacy_client() { - DATA.root_dir.join(LIBRARIES_LEGACY_FOLDER) + DATA.root_dir.lock().unwrap().join(LIBRARIES_LEGACY_FOLDER) } else { - DATA.root_dir.join(LIBRARIES_FOLDER) + DATA.root_dir.lock().unwrap().join(LIBRARIES_FOLDER) }; return Ok(format!( @@ -839,12 +954,17 @@ impl Client { manager: Arc>, ) -> Result<(), String> { if !options.is_custom && SETTINGS.lock().is_ok_and(|s| s.optional_telemetry.value) { - Analytics::send_client_analytics(self.id); + Analytics::send_client_analytics(self.id, &options.user_token); } { let mut logs = CLIENT_LOGS.lock().unwrap(); - logs.insert(self.id, Vec::new()); + let client_logs = logs.entry(self.id).or_insert_with(Vec::new); + if !client_logs.is_empty() { + client_logs.push("-------------------------------------------".to_string()); + client_logs.push(format!("--- New Instance Started ---")); + client_logs.push("-------------------------------------------".to_string()); + } } let app_handle = options.app_handle.clone(); @@ -860,29 +980,55 @@ impl Client { return Err(e); } - let java_bin = self.java_executable_path(); + let java_bin = if let Some(ref path) = self.java_path { + if !path.is_empty() { + PathBuf::from(path) + } else if let Ok(s) = SETTINGS.lock() { + if !s.java_path.value.is_empty() { + PathBuf::from(&s.java_path.value) + } else { + self.java_executable_path() + } + } else { + self.java_executable_path() + } + } else if let Ok(s) = SETTINGS.lock() { + if !s.java_path.value.is_empty() { + PathBuf::from(&s.java_path.value) + } else { + self.java_executable_path() + } + } else { + self.java_executable_path() + }; + let (client_folder, _) = self.get_launch_paths()?; let assets_dir = if self.client_type == ClientType::Fabric { - DATA.root_dir.join(ASSETS_FABRIC_FOLDER) + DATA.root_dir.lock().unwrap().join(ASSETS_FABRIC_FOLDER) } else { - DATA.root_dir.join(ASSETS_FOLDER) + DATA.root_dir.lock().unwrap().join(ASSETS_FOLDER) }; let natives_path = if self.is_legacy_client() { if IS_LINUX { - DATA.root_dir.join(NATIVES_LEGACY_LINUX_FOLDER) + DATA.root_dir + .lock() + .unwrap() + .join(NATIVES_LEGACY_LINUX_FOLDER) } else { DATA.root_dir + .lock() + .unwrap() .join(format!("{}{}", NATIVES_FOLDER, LEGACY_SUFFIX)) } } else if self.meta.is_new { - DATA.root_dir.join(format!( + DATA.root_dir.lock().unwrap().join(format!( "{}{}", NATIVES_FOLDER, if IS_LINUX { LINUX_SUFFIX } else { "" } )) } else { - DATA.root_dir.join(format!( + DATA.root_dir.lock().unwrap().join(format!( "{}{}", NATIVES_FOLDER, if IS_LINUX { @@ -926,7 +1072,7 @@ impl Client { lang, ); - let agent_overlay_path = DATA.root_dir.join(AGENT_OVERLAY_FOLDER); + let agent_overlay_path = DATA.root_dir.lock().unwrap().join(AGENT_OVERLAY_FOLDER); let mut cmd = Command::new(java_bin); @@ -946,28 +1092,30 @@ impl Client { )); } - cmd.arg(format!("-Xmx{ram_mb}M")); + if let Ok(s) = SETTINGS.lock() { + if !s.java_args.value.is_empty() { + for arg in s.java_args.value.split_whitespace() { + cmd.arg(arg); + } + } + } - if self.client_type != ClientType::Fabric { - cmd.arg(format!( - "-Djava.library.path={}{}{}", - natives_path.display(), - PATH_SEPARATOR, - agent_overlay_path.display() - )); - } else { - cmd.arg(format!( - "-Djava.library.path={}", - agent_overlay_path.display() - )); + if let Some(ref args) = self.java_args { + if !args.is_empty() { + for arg in args.split_whitespace() { + cmd.arg(arg); + } + } } - cmd.arg("--add-opens") - .arg("java.base/jdk.internal.misc=ALL-UNNAMED"); - cmd.arg("--add-opens").arg("java.base/sun.misc=ALL-UNNAMED"); - cmd.arg("--add-opens") - .arg("java.base/java.lang=ALL-UNNAMED"); - cmd.arg("--add-opens").arg("java.base/java.io=ALL-UNNAMED"); + cmd.arg(format!("-Xmx{ram_mb}M")); + + cmd.arg(format!( + "-Djava.library.path={}{}{}", + natives_path.display(), + PATH_SEPARATOR, + agent_overlay_path.display() + )); cmd.arg("-cp").arg(classpath).arg(&self.main_class); diff --git a/src-tauri/src/core/clients/custom_clients.rs b/src-tauri/src/core/clients/custom_clients.rs index 1a419329..32a132ee 100644 --- a/src-tauri/src/core/clients/custom_clients.rs +++ b/src-tauri/src/core/clients/custom_clients.rs @@ -19,6 +19,8 @@ pub struct CustomClient { pub is_installed: bool, pub launches: u32, pub insecure: bool, + pub java_path: Option, + pub java_args: Option, } impl CustomClient { @@ -41,6 +43,8 @@ impl CustomClient { is_installed: false, launches: 0, insecure: false, + java_path: None, + java_args: None, } } @@ -72,6 +76,8 @@ impl CustomClient { is_custom: true, size: 0, }, + java_path: self.java_path.clone(), + java_args: self.java_args.clone(), } } diff --git a/src-tauri/src/core/clients/internal/agent_overlay.rs b/src-tauri/src/core/clients/internal/agent_overlay.rs index 72daab9b..0f5e705c 100644 --- a/src-tauri/src/core/clients/internal/agent_overlay.rs +++ b/src-tauri/src/core/clients/internal/agent_overlay.rs @@ -8,6 +8,13 @@ use serde::{Deserialize, Serialize}; use std::fs; use std::path::PathBuf; +#[derive(Debug, Serialize, Deserialize)] +pub struct ApiResponse { + pub success: bool, + pub data: Option, + pub message: Option, +} + #[derive(Debug, Serialize, Deserialize, Clone)] pub struct AgentOverlayInfo { pub agent_hash: String, @@ -25,7 +32,7 @@ pub struct AgentArguments { } impl AgentArguments { - pub const fn new( + pub fn new( token: String, client_name: String, analytics: bool, @@ -81,7 +88,7 @@ impl AgentOverlayManager { let info = Self::get_agent_overlay_info().await?; - let folder = DATA.root_dir.join(AGENT_OVERLAY_FOLDER); + let folder = DATA.root_dir.lock().unwrap().join(AGENT_OVERLAY_FOLDER); if !folder.exists() { log_debug!( "Agent overlay folder missing, creating: {}", @@ -180,12 +187,13 @@ impl AgentOverlayManager { return Err(format!("Backend returned error: {}", response.status())); } - let info: AgentOverlayInfo = response.json().await.map_err(|e| { + let info: ApiResponse = response.json().await.map_err(|e| { log_error!("Failed to parse agent/overlay info response: {}", e); format!("Failed to parse agent/overlay info: {e}") })?; - Ok(info) + info.data + .ok_or_else(|| "No agent/overlay info found".to_string()) } async fn download_file(url: &str, path: &PathBuf) -> Result<(), String> { @@ -223,7 +231,7 @@ impl AgentOverlayManager { pub async fn verify_agent_overlay_files() -> Result { log_debug!("Verifying agent and overlay files..."); - let folder = DATA.root_dir.join(AGENT_OVERLAY_FOLDER); + let folder = DATA.root_dir.lock().unwrap().join(AGENT_OVERLAY_FOLDER); if !folder.exists() { log_debug!( "Agent overlay folder missing during verify, creating: {}", diff --git a/src-tauri/src/core/clients/log_checker.rs b/src-tauri/src/core/clients/log_checker.rs index 40033ad8..09be9f0b 100644 --- a/src-tauri/src/core/clients/log_checker.rs +++ b/src-tauri/src/core/clients/log_checker.rs @@ -20,7 +20,7 @@ enum CrashType { } impl LogChecker { - pub const fn new(client: Client) -> Self { + pub fn new(client: Client) -> Self { Self { client } } diff --git a/src-tauri/src/core/clients/manager.rs b/src-tauri/src/core/clients/manager.rs index 26269802..a9d11612 100644 --- a/src-tauri/src/core/clients/manager.rs +++ b/src-tauri/src/core/clients/manager.rs @@ -1,7 +1,7 @@ -use rand::Rng; +use rand::RngExt; use std::sync::{Arc, Mutex}; use std::{fs::File, io::BufReader}; -use tauri::AppHandle; +use tauri::{AppHandle, Manager}; use super::client::Client; use crate::core::clients::client::Meta; @@ -49,7 +49,7 @@ impl ClientManager { Ok(clients) } - pub fn get_client(manager: &Arc>, client_id: u32, f: F) + pub fn get_client(manager: &Arc>, client_id: u32, f: F) where F: FnOnce(&mut Client), { @@ -67,8 +67,12 @@ impl ClientManager { } let clients_task = tokio::task::spawn_blocking(|| { - if let Some(api_instance) = API.as_ref() { - match api_instance.json::>("clients") { + API.as_ref().map_or_else( + || { + log_warn!("API instance not available. Attempting to load clients from cache."); + Self::load_from_cache("clients.json") + }, + |api_instance| match api_instance.json::>("clients") { Ok(clients) => Ok(clients), Err(e) => { log_warn!( @@ -77,40 +81,49 @@ impl ClientManager { ); Self::load_from_cache("clients.json") } - } - } else { - log_warn!("API instance not available. Attempting to load clients from cache."); - Self::load_from_cache("clients.json") - } + }, + ) }); let fabric_clients_task = tokio::task::spawn_blocking( || -> Result, Box> { - if let Some(api_instance) = API.as_ref() { - api_instance - .json::>("fabric-clients") - .or_else(|e| { - log_warn!("Failed to fetch fabric clients: {}", e); - Ok(Vec::new()) - }) - } else { - Ok(Vec::new()) - } + API.as_ref().map_or_else( + || { + log_warn!("API instance not available. Attempting to load fabric-clients from cache."); + Self::load_from_cache("fabric-clients.json") + }, + |api_instance| match api_instance.json::>("fabric-clients") { + Ok(clients) => Ok(clients), + Err(e) => { + log_warn!( + "Failed to fetch fabric-clients from API: {}. Attempting to load from cache.", + e + ); + Self::load_from_cache("fabric-clients.json") + } + }, + ) }, ); let forge_clients_task = tokio::task::spawn_blocking( || -> Result, Box> { - if let Some(api_instance) = API.as_ref() { - api_instance - .json::>("forge-clients") - .or_else(|e| { - log_warn!("Failed to fetch forge clients: {}", e); - Ok(Vec::new()) - }) - } else { - Ok(Vec::new()) - } + API.as_ref().map_or_else( + || { + log_warn!("API instance not available. Attempting to load forge-clients from cache."); + Self::load_from_cache("forge-clients.json") + }, + |api_instance| match api_instance.json::>("forge-clients") { + Ok(clients) => Ok(clients), + Err(e) => { + log_warn!( + "Failed to fetch forge-clients from API: {}. Attempting to load from cache.", + e + ); + Self::load_from_cache("forge-clients.json") + } + }, + ) }, ); @@ -179,7 +192,12 @@ impl ClientManager { fn load_from_cache( filename: &str, ) -> Result, Box> { - let cache_path = DATA.root_dir.join(API_CACHE_DIR).join(filename); + let cache_path = DATA + .root_dir + .lock() + .unwrap() + .join(API_CACHE_DIR) + .join(filename); if cache_path.exists() { let file = File::open(&cache_path) .map_err(|e| Box::new(e) as Box)?; @@ -215,6 +233,27 @@ impl ClientManager { }), ); + let minimize_to_tray_on_launch = { + let settings = crate::core::storage::settings::SETTINGS.lock().unwrap(); + settings.minimize_to_tray_on_launch.value + }; + + if minimize_to_tray_on_launch { + let running_clients = Client::get_running_clients(&Arc::new(Mutex::new(Self { + clients: self.clients.clone(), + }))); + + let running_custom_clients = + crate::core::clients::custom_clients::CustomClient::get_running_custom_clients(); + + if running_clients.is_empty() && running_custom_clients.is_empty() { + if let Some(window) = app_handle.get_webview_window("main") { + let _ = window.show(); + let _ = window.set_focus(); + } + } + } + Ok(()) } } diff --git a/src-tauri/src/core/network/analytics.rs b/src-tauri/src/core/network/analytics.rs index 528a7c61..4004b687 100644 --- a/src-tauri/src/core/network/analytics.rs +++ b/src-tauri/src/core/network/analytics.rs @@ -10,22 +10,24 @@ impl Analytics { Self::send_analytics( &format!("api/{API_VERSION}/loader/launch"), "start analytics", + None, ); } - pub fn send_client_analytics(client_id: u32) { + pub fn send_client_analytics(client_id: u32, token: &str) { let endpoint = format!("api/{API_VERSION}/clients/launch/{client_id}"); - Self::send_analytics(&endpoint, "client analytics"); + Self::send_analytics(&endpoint, "client analytics", Some(token)); } - pub fn send_client_download_analytics(client_id: u32) { + pub fn send_client_download_analytics(client_id: u32, token: &str) { let endpoint = format!("api/{API_VERSION}/clients/download/{client_id}"); - Self::send_analytics(&endpoint, "client download analytics"); + Self::send_analytics(&endpoint, "client download analytics", Some(token)); } - fn send_analytics(endpoint: &str, analytics_type: &str) { + fn send_analytics(endpoint: &str, analytics_type: &str, token: Option<&str>) { let endpoint = endpoint.to_string(); let analytics_type = analytics_type.to_string(); + let token = token.map(|t| t.to_string()); thread::spawn(move || { let Some(server_url) = Self::get_server_url(&analytics_type) else { @@ -37,7 +39,11 @@ impl Analytics { log_debug!("Sending {} to {}", analytics_type, url); - match client.post(&url).send() { + match client + .post(&url) + .bearer_auth(token.as_deref().unwrap_or("")) + .send() + { Ok(_) => {} Err(e) => { log_debug!("Failed to send {}: {}", analytics_type, e); @@ -47,7 +53,8 @@ impl Analytics { } fn get_server_url(analytics_type: &str) -> Option { - match SERVERS.selected_api.read().unwrap().clone() { + let value = SERVERS.selected_api.read().unwrap().clone(); + match value { Some(server) => Some(server.url), None => { log_debug!("No API server selected for {}", analytics_type); diff --git a/src-tauri/src/core/network/api.rs b/src-tauri/src/core/network/api.rs index c193a452..5d17362d 100644 --- a/src-tauri/src/core/network/api.rs +++ b/src-tauri/src/core/network/api.rs @@ -18,7 +18,7 @@ pub struct Api { impl Api { pub fn json(&self, path: &str) -> Result> { - let cache_dir = DATA.root_dir.join(API_CACHE_DIR); + let cache_dir = DATA.root_dir.lock().unwrap().join(API_CACHE_DIR); cache::ensure_cache_dir(&cache_dir); let cache_file_path = cache::cache_file_path(&cache_dir, path); diff --git a/src-tauri/src/core/network/downloader.rs b/src-tauri/src/core/network/downloader.rs index 3b954354..ee3e672e 100644 --- a/src-tauri/src/core/network/downloader.rs +++ b/src-tauri/src/core/network/downloader.rs @@ -10,37 +10,45 @@ const MAX_RETRIES: u32 = 3; const RETRY_DELAY: Duration = Duration::from_secs(2); pub async fn download_file( - url: &str, + urls: &[String], dest_path: &Path, emit_name: &str, app_handle: Option<&tauri::AppHandle>, ) -> Result<(), String> { let mut last_error = String::from("Unknown error"); - for attempt in 1..=MAX_RETRIES { - if attempt > 1 { - log_warn!( - "Retrying download for {} (Attempt {}/{})", - emit_name, - attempt, - MAX_RETRIES - ); - tokio::time::sleep(RETRY_DELAY).await; - } - - match perform_download(url, dest_path, emit_name, app_handle).await { - Ok(_) => return Ok(()), - Err(e) => { - last_error = e; - log_error!( - "Download failed for {} (Attempt {}/{}): {}", + for url in urls { + for attempt in 1..=MAX_RETRIES { + if attempt > 1 { + log_warn!( + "Retrying download for {} (Attempt {}/{})", emit_name, attempt, - MAX_RETRIES, - last_error + MAX_RETRIES ); + tokio::time::sleep(RETRY_DELAY).await; + } + + match perform_download(url, dest_path, emit_name, app_handle).await { + Ok(_) => return Ok(()), + Err(e) => { + last_error = e; + log_error!( + "Download failed for {} (Attempt {}/{}): {}", + emit_name, + attempt, + MAX_RETRIES, + last_error + ); + } } } + log_warn!( + "Failed to download {} from {} after {} attempts. Trying fallback if available...", + emit_name, + url, + MAX_RETRIES + ); } Err(format!( diff --git a/src-tauri/src/core/network/servers.rs b/src-tauri/src/core/network/servers.rs index 4814d716..5ea6699f 100644 --- a/src-tauri/src/core/network/servers.rs +++ b/src-tauri/src/core/network/servers.rs @@ -3,18 +3,19 @@ use crate::{ log_info, log_warn, }; use reqwest::Client; +use serde::Serialize; use std::sync::{LazyLock, Mutex, RwLock}; use std::time::Duration; use tokio::sync::watch; const REQUEST_TIMEOUT: Duration = Duration::from_secs(10); -#[derive(Debug, Clone, serde::Serialize)] +#[derive(Debug, Clone, Serialize, PartialEq, Eq)] pub struct Server { pub url: String, } -#[derive(Debug, Clone, serde::Serialize)] +#[derive(Debug, Clone, Serialize)] pub struct ServerConnectivityStatus { pub cdn_online: bool, pub api_online: bool, @@ -117,15 +118,28 @@ impl Servers { name: &str, ) { for server in servers { - match client.head(&server.url).send().await { + // if CDN located on same server as API we should check API server instead of CDN, to reduce unused requests + let url = if name == "CDN" { + if let Some(api_server) = self.apis.iter().find(|s| server.url.starts_with(&s.url)) + { + api_server.url.clone() + } else { + server.url.clone() + } + } else { + server.url.clone() + }; + + let mut ok = false; + + match client.head(&url).send().await { Ok(resp) => { - if resp.status().is_success() { - let mut lock = selected.write().unwrap(); - *lock = Some(server.clone()); - return; + if resp.status().is_success() || resp.status() == reqwest::StatusCode::NOT_FOUND + { + ok = true; } else { log_warn!( - "{} Server {} returned status: {}", + "{} Server {} returned status (HEAD): {}", name, server.url, resp.status() @@ -133,9 +147,47 @@ impl Servers { } } Err(e) => { - log_warn!("Failed to connect to {} Server {}: {}", name, server.url, e); + log_warn!( + "Failed to connect to {} Server {} (HEAD): {}", + name, + server.url, + e + ); } } + + if !ok { + match client.get(&url).send().await { + Ok(resp) => { + if resp.status().is_success() + || resp.status() == reqwest::StatusCode::NOT_FOUND + { + ok = true; + } else { + log_warn!( + "{} Server {} returned status (GET): {}", + name, + server.url, + resp.status() + ); + } + } + Err(e) => { + log_warn!( + "Failed to connect to {} Server {} (GET): {}", + name, + server.url, + e + ); + } + } + } + + if ok { + let mut lock = selected.write().unwrap(); + *lock = Some(server.clone()); + return; + } } let mut lock = selected.write().unwrap(); @@ -156,6 +208,14 @@ impl Servers { .as_ref() .map(|server| server.url.clone()) } + + pub fn get_cdn_server_url(&self) -> Option { + self.selected_cdn + .read() + .unwrap() + .as_ref() + .map(|server| server.url.clone()) + } } impl Default for Servers { diff --git a/src-tauri/src/core/storage/custom_clients.rs b/src-tauri/src/core/storage/custom_clients.rs index fa156d20..1a9446f9 100644 --- a/src-tauri/src/core/storage/custom_clients.rs +++ b/src-tauri/src/core/storage/custom_clients.rs @@ -14,11 +14,18 @@ use super::common::JsonStorage; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct CustomClientManager { pub clients: Vec, + #[serde(skip)] pub custom_clients_path: PathBuf, pub next_id: u32, } impl CustomClientManager { + pub fn load_from_disk(path: PathBuf) -> Self { + let mut loaded = ::load_from_disk(path.clone()); + loaded.custom_clients_path = path; + loaded + } + pub fn add_client(&mut self, mut custom_client: CustomClient) -> Result<(), String> { if !custom_client.file_path.exists() { return Err(format!( @@ -122,6 +129,14 @@ impl CustomClientManager { client.main_class = main_class; } + if let Some(java_path) = updates.java_path { + client.java_path = Some(java_path); + } + + if let Some(java_args) = updates.java_args { + client.java_args = Some(java_args); + } + self.save_to_disk(); Ok(()) } else { @@ -135,6 +150,8 @@ pub struct CustomClientUpdate { pub name: Option, pub version: Option, pub main_class: Option, + pub java_path: Option, + pub java_args: Option, } impl JsonStorage for CustomClientManager { diff --git a/src-tauri/src/core/storage/data.rs b/src-tauri/src/core/storage/data.rs index 038b417f..f2e9d735 100644 --- a/src-tauri/src/core/storage/data.rs +++ b/src-tauri/src/core/storage/data.rs @@ -16,7 +16,7 @@ use tokio::fs as tokio_fs; use tokio::task; pub struct Data { - pub root_dir: PathBuf, + pub root_dir: Mutex, } pub static APP_HANDLE: std::sync::LazyLock>> = @@ -42,7 +42,9 @@ impl Data { log_info!("Created root data directory: {}", root_dir.display()); } - Self { root_dir } + Self { + root_dir: Mutex::new(root_dir), + } } pub fn has_extension(file_path: &str, extension: &str) -> bool { @@ -53,7 +55,7 @@ impl Data { pub fn get_local(&self, relative_path: &str) -> PathBuf { let parts: Vec<&str> = relative_path.split(|c| ['/', '\\'].contains(&c)).collect(); - let mut path = self.root_dir.clone(); + let mut path = self.root_dir.lock().unwrap().clone(); for part in parts { if part.is_empty() { continue; @@ -64,20 +66,16 @@ impl Data { } pub async fn unzip(&self, file: &str) -> Result<(), String> { - let (emit_name, local_name) = if file.starts_with("http://") || file.starts_with("https://") - { - ( - file.to_string(), - file.rsplit('/').next().unwrap_or(file).to_string(), - ) - } else { - (file.to_string(), file.to_string()) - }; - - let zip_path = self.get_local(&local_name); - let unzip_path = self.get_local(local_name.trim_end_matches(".zip")); + let info = Self::resolve_local_file_info(file); + let zip_path = self.get_local(&info.local_file); + let unzip_path = self.get_local( + info.local_file + .strip_suffix(".zip") + .unwrap_or(&info.local_file), + ); let app_handle = APP_HANDLE.lock().unwrap().clone(); + let emit_name = info.local_file.clone(); task::spawn_blocking(move || { unzip(&zip_path, &unzip_path, &emit_name, app_handle.as_ref()) @@ -93,7 +91,7 @@ impl Data { .file_stem() .and_then(|s| s.to_str()) .unwrap_or(file); - self.root_dir.join(file_name) + self.root_dir.lock().unwrap().join(file_name) } pub fn get_as_folder_string(file: &str) -> String { @@ -113,15 +111,15 @@ impl Data { } fn resolve_local_file_info(file: &str) -> FileInfo { - let is_url = file.starts_with("http://") || file.starts_with("https://"); - let local_file = if is_url { - file.rsplit('/').next().unwrap_or(file).to_string() + let local_file = if file.starts_with("misc/") { + file.strip_prefix("misc/").unwrap().to_string() } else { - file.to_string() + file.rsplit(['/', '\\']).next().unwrap_or(file).to_string() }; let file_name = Self::get_filename(&local_file); - let is_fabric_client = local_file.starts_with("fabric/") && local_file.ends_with(".jar"); + let is_fabric_client = (file.starts_with("fabric/") || file.contains("/fabric/jars/")) + && local_file.ends_with(".jar"); FileInfo { local_file, @@ -130,36 +128,42 @@ impl Data { } } - fn get_destination_path(&self, file: &str, info: &FileInfo) -> PathBuf { + fn get_destination_path(&self, _file: &str, info: &FileInfo) -> PathBuf { if info.is_fabric_client { - let jar_basename = Path::new(file) - .file_name() - .and_then(|n| n.to_str()) - .unwrap_or(file); + let jar_basename = &info.local_file; self.root_dir + .lock() + .unwrap() .join(&info.file_name) .join("mods") .join(jar_basename) } else if Self::has_extension(&info.local_file, "jar") { - self.root_dir.join(&info.file_name).join(&info.local_file) + self.root_dir + .lock() + .unwrap() + .join(&info.file_name) + .join(&info.local_file) } else { - self.root_dir.join(&info.local_file) + self.root_dir.lock().unwrap().join(&info.local_file) } } fn should_skip_download(&self, info: &FileInfo) -> bool { if Self::has_extension(&info.local_file, "zip") { - let zip_path = self.root_dir.join(&info.local_file); - let unzip_path = self.root_dir.join(info.local_file.trim_end_matches(".zip")); + let zip_path = self.root_dir.lock().unwrap().join(&info.local_file); + let unzip_path = self + .root_dir + .lock() + .unwrap() + .join(info.local_file.trim_end_matches(".zip")); zip_path.exists() && unzip_path.exists() } else if Self::has_extension(&info.local_file, "jar") { if info.is_fabric_client { - let jar_basename = Path::new(&info.local_file) - .file_name() - .and_then(|n| n.to_str()) - .unwrap_or(&info.local_file); + let jar_basename = &info.local_file; let jar_path = self .root_dir + .lock() + .unwrap() .join(&info.file_name) .join("mods") .join(jar_basename); @@ -177,9 +181,28 @@ impl Data { } async fn prepare_download_dirs(&self, info: &FileInfo) -> Result<(), String> { + if let Some(parent) = Path::new(&info.local_file).parent() { + if !parent.as_os_str().is_empty() { + let parent_path = self.root_dir.lock().unwrap().join(parent); + if let Err(e) = tokio_fs::create_dir_all(&parent_path).await { + log_error!( + "Failed to create parent directory {}: {}", + parent_path.display(), + e + ); + return Err(format!("Failed to create directory: {e}")); + } + } + } + if Self::has_extension(&info.local_file, "jar") { if info.is_fabric_client { - let mods_dir = self.root_dir.join(&info.file_name).join("mods"); + let mods_dir = self + .root_dir + .lock() + .unwrap() + .join(&info.file_name) + .join("mods"); if let Err(e) = tokio_fs::create_dir_all(&mods_dir).await { log_error!( "Failed to create fabric mods directory {}: {}", @@ -210,19 +233,30 @@ impl Data { Ok(()) } - fn get_download_url(file: &str) -> Result { + fn get_download_urls(file: &str) -> Result, String> { let is_url = file.starts_with("http://") || file.starts_with("https://"); if is_url { - Ok(file.to_string()) + Ok(vec![file.to_string()]) } else { - let cdn_url = SERVERS.selected_cdn.read().unwrap().as_ref().map_or_else( - || { - log_error!("No CDN server available for download"); - Err("No CDN server available for download.".to_string()) - }, - |server| Ok(server.url.clone()), - )?; - Ok(format!("{cdn_url}{file}")) + let mut urls = Vec::new(); + + if let Some(selected) = SERVERS.selected_cdn.read().unwrap().as_ref() { + urls.push(format!("{}{}", selected.url, file)); + } + + for cdn in &SERVERS.cdns { + let url = format!("{}{}", cdn.url, file); + if !urls.contains(&url) { + urls.push(url); + } + } + + if urls.is_empty() { + log_error!("No CDN server available for download"); + return Err("No CDN server available for download.".to_string()); + } + + Ok(urls) } } @@ -235,19 +269,25 @@ impl Data { } if let Some(app_handle) = APP_HANDLE.lock().unwrap().as_ref() { - emit_to_main_window(app_handle, "download-start", &file); + emit_to_main_window(app_handle, "download-start", &info.local_file); } self.prepare_download_dirs(&info).await?; - let download_url = Self::get_download_url(file)?; + let download_urls = Self::get_download_urls(file)?; let dest_path = self.get_destination_path(file, &info); let app_handle = APP_HANDLE.lock().unwrap().clone(); - download_file(&download_url, &dest_path, file, app_handle.as_ref()).await?; + download_file( + &download_urls, + &dest_path, + &info.local_file, + app_handle.as_ref(), + ) + .await?; if let Some(handle) = app_handle.as_ref() { - emit_to_main_window(handle, "download-complete", &file); + emit_to_main_window(handle, "download-complete", &info.local_file); } if Self::has_extension(&info.local_file, "zip") { @@ -255,7 +295,7 @@ impl Data { log_error!("Failed to extract {}: {}", file, e); if let Some(app_handle) = APP_HANDLE.lock().unwrap().as_ref() { let err_data = serde_json::json!({ - "file": file, + "file": info.local_file, "error": e }); emit_to_main_window(app_handle, "unzip-error", err_data); @@ -268,14 +308,14 @@ impl Data { } pub async fn ensure_client_synced(&self, client_base: &str) -> Result<(), String> { - let global_options_dir = self.root_dir.join("synced_options"); + let global_options_dir = self.root_dir.lock().unwrap().join("synced_options"); if !global_options_dir.exists() { tokio_fs::create_dir_all(&global_options_dir) .await .map_err(|e| format!("Failed to create global options dir: {e}"))?; } - let client_dir = self.root_dir.join(client_base); + let client_dir = self.root_dir.lock().unwrap().join(client_base); if !client_dir.exists() { tokio_fs::create_dir_all(&client_dir) .await @@ -313,8 +353,14 @@ impl Data { } let client_target = client_dir.join(name); - if client_target.exists() { - let res = if client_target.is_dir() { + if let Ok(meta) = tokio_fs::symlink_metadata(&client_target).await { + let res = if meta.file_type().is_symlink() { + if meta.is_dir() { + tokio_fs::remove_dir(&client_target).await + } else { + tokio_fs::remove_file(&client_target).await + } + } else if meta.is_dir() { tokio_fs::remove_dir_all(&client_target).await } else { tokio_fs::remove_file(&client_target).await @@ -329,7 +375,7 @@ impl Data { } } - if let Err(e) = Self::create_symlink(&target, &client_target) { + if let Err(e) = Self::create_symlink(&target, &client_target, is_dir) { log_warn!( "Failed to symlink {} for {}: {} -> {}: {}", name, @@ -344,7 +390,11 @@ impl Data { Ok(()) } - fn create_symlink(src: &std::path::Path, dst: &std::path::Path) -> Result<(), String> { + fn create_symlink( + src: &std::path::Path, + dst: &std::path::Path, + is_dir: bool, + ) -> Result<(), String> { #[cfg(target_family = "unix")] { std::os::unix::fs::symlink(src, dst).map_err(|e| e.to_string()) @@ -353,10 +403,8 @@ impl Data { #[cfg(target_family = "windows")] { use std::os::windows::fs::{symlink_dir, symlink_file}; - if src.is_dir() { + if is_dir { symlink_dir(src, dst).map_err(|e| e.to_string()) - } else if src.is_file() { - symlink_file(src, dst).map_err(|e| e.to_string()) } else { symlink_file(src, dst).map_err(|e| e.to_string()) } @@ -364,13 +412,21 @@ impl Data { } pub async fn download_to_folder(&self, file: &str, dest_folder: &str) -> Result<(), String> { + let info = Self::resolve_local_file_info(file); if let Some(app_handle) = APP_HANDLE.lock().unwrap().as_ref() { - emit_to_main_window(app_handle, "download-start", &file); + emit_to_main_window(app_handle, "download-start", &info.local_file); } - let download_url = Self::get_download_url(file)?; + let download_urls = Self::get_download_urls(file)?; - let dest_dir = self.root_dir.join(dest_folder); + log_debug!( + "Downloading {} to folder {} from URLs: {:?}", + file, + dest_folder, + download_urls + ); + + let dest_dir = self.root_dir.lock().unwrap().join(dest_folder); if let Err(e) = tokio_fs::create_dir_all(&dest_dir).await { log_error!( "Failed to create destination folder {}: {}", @@ -384,20 +440,23 @@ impl Data { let dest_path = dest_dir.join(dest_filename); let app_handle = APP_HANDLE.lock().unwrap().clone(); - download_file(&download_url, &dest_path, file, app_handle.as_ref()).await?; + download_file( + &download_urls, + &dest_path, + &info.local_file, + app_handle.as_ref(), + ) + .await?; if let Some(handle) = app_handle.as_ref() { - emit_to_main_window(handle, "download-complete", &file); + emit_to_main_window(handle, "download-complete", &info.local_file); } Ok(()) } - pub async fn verify_file_md5( - path: &std::path::PathBuf, - expected: &str, - ) -> Result { - let path = path.clone(); + pub async fn verify_file_md5(path: &Path, expected: &str) -> Result { + let path = path.to_path_buf(); let expected = expected.to_lowercase(); let calc = tokio::task::spawn_blocking(move || { crate::core::utils::hashing::calculate_md5_hash(&path) @@ -430,7 +489,7 @@ impl Data { } for requirement in &requirements { - let path = self.root_dir.join(requirement); + let path = self.root_dir.lock().unwrap().join(requirement); if path.exists() { if path.is_dir() { tokio_fs::remove_dir_all(&path) @@ -448,7 +507,7 @@ impl Data { } pub async fn reset_cache(&self) -> Result<(), String> { - let cache_dir = self.root_dir.join("cache"); + let cache_dir = self.root_dir.lock().unwrap().join("cache"); if cache_dir.exists() { tokio_fs::remove_dir_all(&cache_dir) .await @@ -473,14 +532,11 @@ impl Data { return false; } - match std::fs::read_dir(&path) { - Ok(mut entries) => entries.next().is_some(), - Err(_) => false, - } + std::fs::read_dir(&path).is_ok_and(|mut entries| entries.next().is_some()) } pub fn verify_folder_integrity(&self, folder_name: &str) -> bool { - let folder_path = self.root_dir.join(folder_name); + let folder_path = self.root_dir.lock().unwrap().join(folder_name); let manifest_path = folder_path.join("manifest.txt"); if !manifest_path.exists() { diff --git a/src-tauri/src/core/storage/flags.rs b/src-tauri/src/core/storage/flags.rs index b76f8702..2b0a2a30 100644 --- a/src-tauri/src/core/storage/flags.rs +++ b/src-tauri/src/core/storage/flags.rs @@ -10,7 +10,7 @@ pub struct Flag { } impl Flag { - pub const fn new(value: T) -> Self { + pub fn new(value: T) -> Self { Self { value } } } diff --git a/src-tauri/src/core/storage/presets.rs b/src-tauri/src/core/storage/presets.rs index d580a010..9cd55ab6 100644 --- a/src-tauri/src/core/storage/presets.rs +++ b/src-tauri/src/core/storage/presets.rs @@ -11,7 +11,9 @@ pub struct ThemePreset { pub name: String, pub description: Option, pub created_at: String, + #[serde(rename = "customCSS", alias = "customCss")] pub custom_css: String, + #[serde(rename = "enableCustomCSS", alias = "enableCustomCss")] pub enable_custom_css: bool, pub base100: Option, @@ -35,11 +37,19 @@ pub struct ThemePreset { pub warning_content: Option, pub error: Option, pub error_content: Option, + + #[serde(rename = "backgroundImage")] + pub background_image: Option, + #[serde(rename = "backgroundBlur")] + pub background_blur: Option, + #[serde(rename = "backgroundOpacity")] + pub background_opacity: Option, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct PresetManager { pub presets: HashMap, + #[serde(skip)] pub config_path: PathBuf, } @@ -67,6 +77,12 @@ impl JsonStorage for PresetManager { } impl PresetManager { + pub fn load_from_disk(path: PathBuf) -> Self { + let mut loaded = ::load_from_disk(path.clone()); + loaded.config_path = path; + loaded + } + pub fn add_preset(&mut self, preset: ThemePreset) -> Result<(), String> { if self.presets.contains_key(&preset.id) { return Err(format!( diff --git a/src-tauri/src/core/storage/settings.rs b/src-tauri/src/core/storage/settings.rs index 0460be1d..6306682c 100644 --- a/src-tauri/src/core/storage/settings.rs +++ b/src-tauri/src/core/storage/settings.rs @@ -18,7 +18,7 @@ pub struct Setting { } impl Setting { - pub const fn new(value: T, show: bool) -> Self { + pub fn new(value: T, show: bool) -> Self { Self { value, show } } } @@ -81,7 +81,7 @@ macro_rules! define_settings { $( $field: Setting { value: input.$field.value, - show: input.$field.show, + show: $show_val, }, )* config_path, @@ -92,6 +92,9 @@ macro_rules! define_settings { // update config_path here, because value is computed at runtime let mut loaded = ::load_from_disk(path.clone()); loaded.config_path = path; + $( + loaded.$field.show = $show_val; + )* loaded } } @@ -125,6 +128,10 @@ define_settings! { hash_verify: Setting = (true, true), sync_client_settings: Setting = (true, true), dpi_bypass: Setting = (false, true), + minimize_to_tray_on_launch: Setting = (false, true), + close_to_tray: Setting = (false, true), + java_path: Setting = ("".to_string(), true), + java_args: Setting = ("".to_string(), true), } } diff --git a/src-tauri/src/core/utils/dpi.rs b/src-tauri/src/core/utils/dpi.rs index a5d03f45..fa189131 100644 --- a/src-tauri/src/core/utils/dpi.rs +++ b/src-tauri/src/core/utils/dpi.rs @@ -8,10 +8,8 @@ use crate::core::utils::helpers::emit_to_main_window; use crate::core::utils::helpers::is_development_enabled; #[cfg(target_os = "windows")] use crate::messagebox; -#[cfg(target_os = "windows")] -use crate::{log_error, log_warn}; -use crate::log_info; +use crate::{log_debug, log_error, log_info, log_warn}; #[cfg(target_os = "windows")] const DPI_RELEASE_API: &str = @@ -23,6 +21,39 @@ const DPI_ZIP_NAME: &str = "ZapretCollapseLoader.zip"; #[cfg(target_os = "windows")] const DPI_FOLDER_NAME: &str = "ZapretCollapseLoader"; +#[cfg(target_os = "windows")] +pub fn kill_winws() { + use std::os::windows::process::CommandExt; + use std::process::Command; + + log_info!("Attempting to kill any existing winws.exe processes"); + + let mut cmd = Command::new("taskkill"); + cmd.args(["/F", "/IM", "winws.exe", "/T"]); + + if !is_development_enabled() { + cmd.creation_flags(0x08000000); // CREATE_NO_WINDOW + } + + match cmd.output() { + Ok(output) => { + if output.status.success() { + log_info!("Successfully killed existing winws.exe processes"); + } else { + let stderr = String::from_utf8_lossy(&output.stderr); + if stderr.contains("not found") || stderr.contains("не найден") { + log_debug!("No winws.exe processes were found to kill"); + } else { + log_warn!("taskkill returned non-zero status: {}", stderr); + } + } + } + Err(e) => { + log_error!("Failed to execute taskkill: {}", e); + } + } +} + #[cfg(target_os = "windows")] pub fn enable_dpi_bypass_async() -> Result<(), String> { let app_handle_clone = APP_HANDLE.lock().unwrap().clone(); @@ -40,8 +71,20 @@ pub fn enable_dpi_bypass_async() -> Result<(), String> { "toast-error", "Failed to enable DPI bypass due to insufficient privileges. Please run the application as administrator and try again.", ); + } else { + emit_to_main_window( + app_handle, + "toast-error", + format!("Failed to enable DPI bypass: {}", e), + ); } } + } else if let Some(app_handle) = app_handle_clone.as_ref() { + emit_to_main_window( + app_handle, + "toast-success", + "DPI bypass enabled successfully", + ); } }); Ok(()) @@ -63,7 +106,10 @@ pub fn download_dpi_bypass() -> Result<(), String> { if r.status().is_success() { match r.json::() { Ok(json) => { - if let Some(assets) = json.get("assets").and_then(|v| v.as_array()) { + json.get("assets").and_then(|v| v.as_array()).map_or_else(|| { + log_warn!("No assets field in GitHub release JSON; falling back to hardcoded URL"); + DPI_ZIP_FALLBACK_URL.to_string() + }, |assets| { let mut found: Option = None; for asset in assets { if asset.get("name").and_then(|n| n.as_str()) == Some(DPI_ZIP_NAME) @@ -76,19 +122,16 @@ pub fn download_dpi_bypass() -> Result<(), String> { } } } - if let Some(u) = found { + found.map_or_else(|| { + log_warn!("Asset {} not found in latest release; falling back to hardcoded URL", DPI_ZIP_NAME); + DPI_ZIP_FALLBACK_URL.to_string() + }, |u| { log_info!( "Resolved latest DPI package URL from GitHub releases API" ); u - } else { - log_warn!("Asset {} not found in latest release; falling back to hardcoded URL", DPI_ZIP_NAME); - DPI_ZIP_FALLBACK_URL.to_string() - } - } else { - log_warn!("No assets field in GitHub release JSON; falling back to hardcoded URL"); - DPI_ZIP_FALLBACK_URL.to_string() - } + }) + }) } Err(e) => { log_warn!("Failed to parse GitHub release JSON: {}. Falling back to hardcoded URL", e); @@ -156,8 +199,10 @@ fn start_winws_background_inner() -> Result<(), String> { return Ok(()); } + kill_winws(); + use std::path::PathBuf; - let base_dir: PathBuf = DATA.root_dir.join(DPI_FOLDER_NAME); + let base_dir: PathBuf = DATA.root_dir.lock().unwrap().join(DPI_FOLDER_NAME); let bin_dir = base_dir.join("bin"); let lists_dir = base_dir.join("lists"); let winws_path = bin_dir.join("winws.exe"); @@ -178,11 +223,9 @@ fn start_winws_background_inner() -> Result<(), String> { } fn extend_with_game_filter(base: &str, game_filter: &Option) -> String { - if let Some(filter) = game_filter { - format!("{},{}", base, filter) - } else { - base.to_string() - } + game_filter + .as_ref() + .map_or_else(|| base.to_string(), |filter| format!("{},{}", base, filter)) } let game_filter = std::env::var("GameFilter") @@ -381,6 +424,15 @@ fn start_winws_background_inner() -> Result<(), String> { winws_path.display(), e ); + + if let Some(app_handle) = APP_HANDLE.lock().unwrap().as_ref() { + emit_to_main_window( + app_handle, + "toast-error", + format!("Failed to start DPI bypass process: {}", e), + ); + } + return Err(format!("Failed to start winws.exe: {}", e)); } } diff --git a/src-tauri/src/core/utils/globals.rs b/src-tauri/src/core/utils/globals.rs index 4e6a394b..7bcf5165 100644 --- a/src-tauri/src/core/utils/globals.rs +++ b/src-tauri/src/core/utils/globals.rs @@ -2,7 +2,7 @@ use std::{fs, path::PathBuf, sync::LazyLock}; use crate::{core::network::servers::Server, log_debug, log_info}; -pub static CODENAME: &str = "Abyss"; +pub static CODENAME: &str = "Atlas"; pub static API_VERSION: &str = "v1"; @@ -31,27 +31,27 @@ pub static JDK8_ZIP: &str = if IS_LINUX { pub static JDK_FOLDERS: LazyLock> = LazyLock::new(|| vec![JDK21_FOLDER, JDK8_FOLDER]); pub static ASSETS_FOLDER: &str = "assets"; -pub static ASSETS_FABRIC_FOLDER: &str = "assets_fabric"; +pub static ASSETS_FABRIC_FOLDER: &str = "assets-fabric"; pub static LIBRARIES_FOLDER: &str = "libraries"; -pub static LIBRARIES_FABRIC_FOLDER: &str = "libraries_fabric"; +pub static LIBRARIES_FABRIC_FOLDER: &str = "libraries-fabric"; pub static LIBRARIES_LEGACY_FOLDER: &str = "libraries-legacy"; pub static NATIVES_FOLDER: &str = "natives"; pub static NATIVES_LINUX_FOLDER: &str = "natives-linux"; pub static NATIVES_LEGACY_FOLDER: &str = "natives-legacy"; pub static NATIVES_LEGACY_LINUX_FOLDER: &str = "natives-legacy-linux"; -pub static NATIVES_FABRIC_FOLDER: &str = "natives_fabric"; - -pub static ASSETS_ZIP: &str = "assets.zip"; -pub static ASSETS_FABRIC_ZIP: &str = "assets_fabric.zip"; -pub static LIBRARIES_ZIP: &str = "libraries.zip"; -pub static LIBRARIES_FABRIC_ZIP: &str = "libraries_fabric.zip"; -pub static LIBRARIES_LEGACY_ZIP: &str = "libraries-legacy.zip"; -pub static NATIVES_ZIP: &str = "natives.zip"; -pub static NATIVES_LINUX_ZIP: &str = "natives-linux.zip"; -pub static NATIVES_LEGACY_ZIP: &str = "natives-legacy.zip"; -pub static NATIVES_LEGACY_LINUX_ZIP: &str = "natives-legacy-linux.zip"; - -pub static MINECRAFT_VERSIONS_FOLDER: &str = "minecraft_versions"; +pub static NATIVES_FABRIC_FOLDER: &str = "natives-fabric"; + +pub static ASSETS_ZIP: &str = "misc/assets.zip"; +pub static ASSETS_FABRIC_ZIP: &str = "misc/assets-fabric.zip"; +pub static LIBRARIES_ZIP: &str = "misc/libraries.zip"; +pub static LIBRARIES_FABRIC_ZIP: &str = "misc/libraries-fabric.zip"; +pub static LIBRARIES_LEGACY_ZIP: &str = "misc/libraries-legacy.zip"; +pub static NATIVES_ZIP: &str = "misc/natives.zip"; +pub static NATIVES_LINUX_ZIP: &str = "misc/natives-linux.zip"; +pub static NATIVES_LEGACY_ZIP: &str = "misc/natives-legacy.zip"; +pub static NATIVES_LEGACY_LINUX_ZIP: &str = "misc/natives-legacy-linux.zip"; + +pub static MINECRAFT_VERSIONS_FOLDER: &str = "minecraft-versions"; pub static AGENT_OVERLAY_FOLDER: &str = "agent_overlay"; pub static CUSTOM_CLIENTS_FOLDER: &str = "custom_clients"; pub static MODS_FOLDER: &str = "mods"; @@ -61,6 +61,9 @@ pub static OVERLAY_FILE: &str = "CollapseOverlay.dll"; pub static IRC_HOST: &str = "irc.collapseloader.org:1338"; +pub static FABRIC_DEPS_URL: &str = "clients/fabric/deps/jars"; +pub static FORGE_DEPS_URL: &str = "clients/forge/deps/jars"; + fn parse_env_bool(var: &str) -> bool { std::env::var(var).ok().is_some_and(|s| { let s = s.trim().to_ascii_lowercase(); @@ -73,33 +76,30 @@ pub static SKIP_AGENT_OVERLAY_VERIFICATION: LazyLock = pub static MOCK_CLIENTS: LazyLock = LazyLock::new(|| parse_env_bool("MOCK_CLIENTS")); -pub static CDN_SERVERS: LazyLock> = LazyLock::new(|| { - if let Ok(url) = std::env::var("FORCE_CDN") { +pub static API_SERVERS: LazyLock> = LazyLock::new(|| { + if let Ok(url) = std::env::var("FORCE_API") { if !url.is_empty() { - log_info!("Using forced CDN server: {}", url); + log_info!("Using forced API server: {}", url); return vec![Server::new(&url)]; } } + vec![ - Server::new("https://cdn.collapseloader.org/"), - Server::new("https://collapse.ttfdk.lol/cdn/"), - Server::new( - "https://axkanxneklh7.objectstorage.eu-amsterdam-1.oci.customer-oci.com/n/axkanxneklh7/b/collapse/o/", - ), + Server::new("https://atlas.collapseloader.org/"), + Server::new("http://141.148.224.27/atlas/"), ] }); -pub static API_SERVERS: LazyLock> = LazyLock::new(|| { - if let Ok(url) = std::env::var("FORCE_API") { +pub static CDN_SERVERS: LazyLock> = LazyLock::new(|| { + if let Ok(url) = std::env::var("FORCE_CDN") { if !url.is_empty() { - log_info!("Using forced API server: {}", url); + log_info!("Using forced CDN server: {}", url); return vec![Server::new(&url)]; } } - vec![ - Server::new("https://atlas.collapseloader.org/"), - Server::new("https://collapse.ttfdk.lol/auth/"), + Server::new("https://atlas-test.collapseloader.org/uploads/"), + Server::new("http://141.148.224.27/cdn/"), ] }); diff --git a/src-tauri/src/core/utils/logging.rs b/src-tauri/src/core/utils/logging.rs index 46c9604c..d7597a4a 100644 --- a/src-tauri/src/core/utils/logging.rs +++ b/src-tauri/src/core/utils/logging.rs @@ -45,11 +45,9 @@ impl Logger { } let mut shorted_tag = { - let slice = if let Some(pos) = tag.rfind("collapseloader_lib.") { - &tag[pos + "collapseloader_lib.".len()..] - } else { - tag - }; + let slice = tag + .rfind("collapseloader_lib.") + .map_or(tag, |pos| &tag[pos + "collapseloader_lib.".len()..]); slice.replace("collapse.module.collapseloader_lib", "core.init") }; diff --git a/src-tauri/src/core/utils/process.rs b/src-tauri/src/core/utils/process.rs index 27216cd2..b2bdae0b 100644 --- a/src-tauri/src/core/utils/process.rs +++ b/src-tauri/src/core/utils/process.rs @@ -10,6 +10,8 @@ pub fn get_jps_path() -> std::path::PathBuf { for folder in JDK_FOLDERS.iter() { let path = DATA .root_dir + .lock() + .unwrap() .join(folder) .join("bin") .join("jps".to_owned() + FILE_EXTENSION); @@ -19,6 +21,8 @@ pub fn get_jps_path() -> std::path::PathBuf { } DATA.root_dir + .lock() + .unwrap() .join(JDK21_FOLDER) .join("bin") .join("jps".to_owned() + FILE_EXTENSION) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 5593b698..9f51c502 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -5,6 +5,9 @@ use crate::core::utils::discord_rpc; use crate::{core::storage::data::APP_HANDLE, logging::Logger}; use std::sync::OnceLock; use std::sync::{Arc, Mutex}; +use std::time::{Duration, Instant}; +use tauri::menu::{Menu, MenuItem}; +use tauri::tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}; use tauri::Manager; use crate::core::{platform::check_platform_dependencies, utils::globals::CODENAME}; @@ -36,7 +39,7 @@ pub fn check_webkit_warning() -> Result<(), StartupError> { #[cfg(target_os = "windows")] pub fn handle_startup_error(error: &StartupError) { - if let StartupError::WebView2NotInstalled = error { + if matches!(error, StartupError::WebView2NotInstalled) { let should_install = messagebox::show_confirm( "WebView2 Not Installed", "WebView2 is not installed. Would you like to download and install it now?", @@ -74,36 +77,81 @@ pub fn handle_startup_error(error: &StartupError) { error.show_and_exit(); } -fn handle_deep_link_url(app: &tauri::AppHandle, url: String) { - if let Some(window) = app.get_webview_window("main") { - let _ = window.set_focus(); +fn handle_deep_link_url(app: &tauri::AppHandle, url: String, was_already_running: bool) { + if was_already_running { + if let Some(window) = app.get_webview_window("main") { + let _ = window.set_focus(); + let _ = window.show(); + } } - log_debug!("Handling deep link URL: {}", url); + log_debug!( + "Handling deep link URL: {} (already running: {})", + url, + was_already_running + ); - if !should_handle_deep_link(&url) { + if !should_handle_deep_link(&url) && was_already_running { log_debug!("Deep link already handled, skipping: {}", url); return; } + if url.contains("verify") { + if let Some(query_part) = url.split("?").nth(1) { + let mut code = String::new(); + let mut email = String::new(); + + for pair in query_part.split('&') { + if let Some((key, value)) = pair.split_once('=') { + match key { + "code" => code = value.to_string(), + "email" => email = value.to_string(), + _ => {} + } + } + } + + if !code.is_empty() { + log_debug!("Emitting verify-email event for code: {}", code); + emit_to_main_window( + app, + "verify-email", + serde_json::json!({ "code": code, "email": email }), + ); + return; + } + } + } + if let Some(client_name) = url.split("client=").nth(1) { let client_name = client_name.split('&').next().unwrap_or(""); log_debug!("Launching client from deep link: {}", client_name); - emit_to_main_window(app, "launch-client", client_name); + emit_to_main_window( + app, + "launch-client", + serde_json::json!({ + "id": client_name, + "was_already_running": was_already_running + }), + ); } } fn should_handle_deep_link(url: &str) -> bool { - static LAST_HANDLED_URL: OnceLock>> = OnceLock::new(); - let last_url = LAST_HANDLED_URL.get_or_init(|| Mutex::new(None)); - let mut guard = last_url.lock().unwrap(); + static LAST_HANDLED: OnceLock>> = OnceLock::new(); + let last = LAST_HANDLED.get_or_init(|| Mutex::new(None)); + let mut guard = last.lock().unwrap(); let normalized = url.trim().to_string(); - if guard.as_ref() == Some(&normalized) { - return false; + if let Some((ref prev, prev_time)) = guard.as_ref() { + if prev == &normalized { + if prev_time.elapsed() < Duration::from_secs(2) { + return false; + } + } } - *guard = Some(normalized); + *guard = Some((normalized, Instant::now())); true } @@ -117,8 +165,8 @@ pub fn run() { .plugin(tauri_plugin_fs::init()) .plugin(tauri_plugin_deep_link::init()) .plugin(tauri_plugin_single_instance::init(|app, args, _cwd| { - if args.len() > 1 { - handle_deep_link_url(app, args[1].clone()); + if let Some(url) = args.iter().find(|a| a.starts_with("collapseloader://")) { + handle_deep_link_url(app, url.clone(), true); } })) .manage(AppState::new(Arc::new( @@ -126,163 +174,86 @@ pub fn run() { ))) .manage(commands::irc::IrcState::default()) .invoke_handler(tauri::generate_handler![ + // client commands + commands::clients::add_custom_client, + commands::clients::delete_client, + commands::clients::detect_main_class, + commands::clients::download_client_only, + commands::clients::get_app_logs, + commands::clients::get_client_logs, + commands::clients::get_clients, + commands::clients::get_custom_clients, + commands::clients::get_latest_client_logs, + commands::clients::get_running_client_ids, + commands::clients::get_running_custom_client_ids, + commands::clients::increment_client_counter, commands::clients::initialize_api, commands::clients::initialize_rpc, - commands::clients::get_server_connectivity_status, - commands::clients::get_clients, - commands::clients::get_client_details, + commands::clients::install_mod_from_url, commands::clients::launch_client, - commands::clients::get_running_client_ids, - commands::clients::stop_client, - commands::clients::get_client_logs, - commands::clients::get_app_logs, - commands::clients::download_client_only, - commands::clients::reinstall_client, + commands::clients::launch_custom_client, + commands::clients::list_installed_mods, commands::clients::open_client_folder, - commands::clients::get_latest_client_logs, - commands::clients::update_client_installed_status, - commands::clients::delete_client, - commands::clients::increment_client_counter, - commands::clients::get_custom_clients, - commands::clients::add_custom_client,package org.collapseloader.atlas.domain.presets.entity; - -import jakarta.persistence.*; -import lombok.*; -import org.collapseloader.atlas.domain.users.entity.User; -import org.hibernate.annotations.CreationTimestamp; -import org.hibernate.annotations.UpdateTimestamp; - -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; - -@Entity -@Table( - name = "presets", - indexes = { - @Index(name = "presets_owner_idx", columnList = "owner_id"), - @Index(name = "presets_public_idx", columnList = "is_public"), - @Index(name = "presets_created_idx", columnList = "created_at") - } -) -@Getter -@Setter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class Preset { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "owner_id", nullable = false) - @ToString.Exclude - private User owner; - - @Column(name = "name", nullable = false, length = 120) - private String name; - - @Column(length = 2048) - private String description; - - @Column(name = "is_public", nullable = false) - private boolean isPublic = true; - - @Embedded - private PresetTheme theme; - - @Column(name = "likes_count", nullable = false) - private long likesCount; - - @Column(name = "downloads_count", nullable = false) - private long downloadsCount; - - @Column(name = "comments_count", nullable = false) - private long commentsCount; - - @OneToMany(mappedBy = "preset", cascade = CascadeType.ALL, orphanRemoval = true) - @ToString.Exclude - @Builder.Default - private List likes = new ArrayList<>(); - - @OneToMany(mappedBy = "preset", cascade = CascadeType.ALL, orphanRemoval = true) - @ToString.Exclude - @Builder.Default - private List comments = new ArrayList<>(); - - @CreationTimestamp - @Column(name = "created_at", updatable = false) - private Instant createdAt; - - @UpdateTimestamp - @Column(name = "updated_at") - private Instant updatedAt; - - @PrePersist - private void ensureTheme() { - if (theme == null) { - theme = new PresetTheme(); - } - } -} - + commands::clients::reinstall_client, commands::clients::remove_custom_client, - commands::clients::update_custom_client, - commands::clients::launch_custom_client, - commands::clients::get_running_custom_client_ids, + commands::clients::stop_client, commands::clients::stop_custom_client, - commands::clients::detect_main_class, - commands::clients::get_client_comments, - commands::clients::add_client_comment, - commands::clients::delete_client_comment, - commands::presets::get_all_presets, - commands::presets::get_preset, + commands::clients::update_client_installed_status, + commands::clients::update_custom_client, + // irc commands + commands::irc::connect_irc, + commands::irc::disconnect_irc, + commands::irc::send_irc_message, + // preset commands commands::presets::create_preset, - commands::presets::update_preset, commands::presets::delete_preset, commands::presets::duplicate_preset, + commands::presets::get_all_presets, + commands::presets::get_preset, + commands::presets::update_preset, + // settings commands + commands::settings::add_account, + commands::settings::add_favorite_client, + commands::settings::get_accounts, + commands::settings::get_active_account, + commands::settings::get_favorite_clients, + commands::settings::get_flags, commands::settings::get_settings, - commands::settings::save_settings, - commands::settings::reset_settings, + commands::settings::get_system_memory, + commands::settings::is_client_favorite, + commands::settings::is_telemetry_consent_shown, commands::settings::mark_disclaimer_shown, commands::settings::mark_first_run_shown, - commands::settings::set_optional_telemetry, commands::settings::mark_telemetry_consent_shown, - commands::settings::is_telemetry_consent_shown, - commands::settings::set_custom_clients_display, - commands::settings::get_flags, - commands::settings::get_accounts, - commands::settings::add_account, commands::settings::remove_account, - commands::settings::set_active_account, - commands::settings::update_account, - commands::settings::get_active_account, - commands::settings::reset_flags, - commands::settings::get_favorite_clients, - commands::settings::add_favorite_client, commands::settings::remove_favorite_client, + commands::settings::reset_flags, + commands::settings::reset_settings, + commands::settings::save_settings, + commands::settings::set_active_account, commands::settings::set_all_favorites, - commands::settings::is_client_favorite, - commands::settings::get_system_memory, - commands::utils::get_version, - commands::utils::is_development, + commands::settings::set_custom_clients_display, + commands::settings::set_optional_telemetry, + commands::settings::update_account, + // updater commands + commands::updater::check_for_updates, + commands::updater::download_and_install_update, + commands::updater::get_changelog, + // utils commands + commands::utils::change_data_folder, + commands::utils::decode_base64, + commands::utils::encode_base64, commands::utils::get_api_url, commands::utils::get_api_version, + commands::utils::get_cdn_url, + commands::utils::get_data_folder, + commands::utils::get_version, + commands::utils::is_development, commands::utils::open_data_folder, commands::utils::reset_requirements, - commands::utils::get_data_folder, - commands::utils::change_data_folder, - commands::utils::decode_base64, - commands::utils::encode_base64, commands::utils::update_presence, - commands::updater::check_for_updates, - commands::updater::download_and_install_update, - commands::updater::get_changelog, - commands::irc::connect_irc, - commands::irc::disconnect_irc, - commands::irc::send_irc_message, + // server connectivity + commands::clients::get_server_connectivity_status, ]) .setup(|app| { #[cfg(desktop)] @@ -290,7 +261,7 @@ public class Preset { use tauri_plugin_deep_link::DeepLinkExt; let handle = app.handle().clone(); app.deep_link().on_open_url(move |event| { - handle_deep_link_url(&handle, event.urls()[0].to_string()); + handle_deep_link_url(&handle, event.urls()[0].to_string(), true); }); app.deep_link().register_all()?; } @@ -301,7 +272,7 @@ public class Preset { let url_clone = url.clone(); spawn(async move { tokio::time::sleep(std::time::Duration::from_millis(2000)).await; - handle_deep_link_url(&handle, url_clone); + handle_deep_link_url(&handle, url_clone, false); }); } @@ -340,6 +311,53 @@ public class Preset { Analytics::send_start_analytics(); }); + let show = MenuItem::with_id(app, "show", "Show", true, None::<&str>)?; + let hide = MenuItem::with_id(app, "hide", "Hide", true, None::<&str>)?; + let quit = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?; + let menu = Menu::with_items(app, &[&show, &hide, &quit])?; + + let _tray = TrayIconBuilder::new() + .icon(app.default_window_icon().unwrap().clone()) + .menu(&menu) + .show_menu_on_left_click(false) + .on_menu_event(|app, event| match event.id.as_ref() { + "show" => { + if let Some(window) = app.get_webview_window("main") { + let _ = window.show(); + let _ = window.set_focus(); + } + } + "hide" => { + if let Some(window) = app.get_webview_window("main") { + let _ = window.hide(); + } + } + "quit" => { + app.exit(0); + } + _ => {} + }) + .on_tray_icon_event(|tray, event| { + if let TrayIconEvent::Click { + button: MouseButton::Left, + button_state: MouseButtonState::Up, + .. + } = event + { + let app = tray.app_handle(); + if let Some(window) = app.get_webview_window("main") { + let is_visible = window.is_visible().unwrap_or(true); + if is_visible { + let _ = window.hide(); + } else { + let _ = window.show(); + let _ = window.set_focus(); + } + } + } + }) + .build(app)?; + #[cfg(target_os = "windows")] { use crate::core::utils::dpi; @@ -348,9 +366,15 @@ public class Preset { Ok(()) }) - .on_window_event(|_window, event| { - if let tauri::WindowEvent::CloseRequested { .. } = event { - discord_rpc::shutdown(); + .on_window_event(|window, event| { + if let tauri::WindowEvent::CloseRequested { api, .. } = event { + let settings = crate::core::storage::settings::SETTINGS.lock().unwrap(); + if settings.close_to_tray.value { + api.prevent_close(); + let _ = window.hide(); + } else { + discord_rpc::shutdown(); + } } }) .run(tauri::generate_context!()) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index a1f0ced8..94b6ec8a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "collapseloader", - "version": "0.2.7", + "version": "0.2.8", "identifier": "org.collapseloader", "build": { "beforeDevCommand": "npm run dev", @@ -45,4 +45,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index 5ab7c6aa..57e15e30 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,44 +1,49 @@ - \ No newline at end of file + diff --git a/src/components/common/LogViewer.vue b/src/components/common/LogViewer.vue index 581cc949..ccd7369f 100644 --- a/src/components/common/LogViewer.vue +++ b/src/components/common/LogViewer.vue @@ -1,9 +1,9 @@ @@ -110,20 +110,28 @@ const close = () => {
-

{{ t('logs.title', { client: clientName }) }}

+

{{ t("logs.title", { client: clientName }) }}

-
+
- {{ t('appLogs.noLogs') }} + {{ t("appLogs.noLogs") }}
{{ logs.join('\n') }}
@@ -211,7 +219,7 @@ const close = () => { overflow-y: auto; overflow-x: hidden; padding: 16px; - font-family: 'Consolas', 'Monaco', monospace; + font-family: "Consolas", "Monaco", monospace; font-size: 13px; line-height: 1.5; white-space: pre-wrap; diff --git a/src/components/common/SearchBar.vue b/src/components/common/SearchBar.vue index 36bcf53b..72285321 100644 --- a/src/components/common/SearchBar.vue +++ b/src/components/common/SearchBar.vue @@ -1,18 +1,37 @@ \ No newline at end of file + diff --git a/src/components/common/SyncStatus.vue b/src/components/common/SyncStatus.vue index 4fae5125..2ee56e66 100644 --- a/src/components/common/SyncStatus.vue +++ b/src/components/common/SyncStatus.vue @@ -1,27 +1,38 @@ diff --git a/src/components/core/InitialSetupModals.vue b/src/components/core/InitialSetupModals.vue index 2ae2ad51..dcfad845 100644 --- a/src/components/core/InitialSetupModals.vue +++ b/src/components/core/InitialSetupModals.vue @@ -1,15 +1,15 @@ + + diff --git a/src/components/core/Preloader.vue b/src/components/core/Preloader.vue index c5a14df2..d3f6e369 100644 --- a/src/components/core/Preloader.vue +++ b/src/components/core/Preloader.vue @@ -1,137 +1,278 @@ \ No newline at end of file + diff --git a/src/components/features/PresetManager.vue b/src/components/features/PresetManager.vue index 9e598be2..e78da3d5 100644 --- a/src/components/features/PresetManager.vue +++ b/src/components/features/PresetManager.vue @@ -2,50 +2,64 @@
-

{{ $t('theme.presets.title') }}

+

+ {{ $t("theme.presets.title") }} +

- {{ $t('theme.presets.description') }} + {{ $t("theme.presets.description") }}

-

{{ $t('theme.presets.loading') }}

+

+ {{ $t("theme.presets.loading") }} +

-

{{ $t('theme.presets.no_presets_title') }}

+

+ {{ $t("theme.presets.no_presets_title") }} +

- {{ $t('theme.presets.no_presets_description') }} + {{ $t("theme.presets.no_presets_description") }}

- {{ $t('theme.presets.pagination.page_of', { current: currentPage, total: totalPages }) }} + {{ + $t("theme.presets.pagination.page_of", { + current: currentPage, + total: totalPages, + }) + }}
- @@ -54,53 +68,81 @@
-
-
+
+ :class="{ + 'ring ring-primary ring-offset-1 ring-offset-base-100 border-primary/60': + isPresetSelected(preset.id), + }" + @click="handlePresetClick(preset, $event)" + >
-

{{ preset.name }}

-

+

+ {{ preset.name }} +

+

{{ preset.description }}

- {{ $t('theme.presets.created', { date: formatDate(preset.createdAt) }) }} + {{ + $t("theme.presets.created", { + date: formatDate(preset.createdAt), + }) + }}
-
@@ -121,62 +170,109 @@
- -
{{ $t('theme.presets.pagination.page_of', { - current: - currentPage, total: totalPages - }) }}
- + +
+ {{ + $t("theme.presets.pagination.page_of", { + current: currentPage, + total: totalPages, + }) + }} +
+
-
+
- {{ $t('theme.presets.selected_count', { count: selectedPresets.size }) }} + {{ + $t("theme.presets.selected_count", { + count: selectedPresets.size, + }) + }}
- - - -
-
- -
@@ -185,20 +281,27 @@ @@ -506,4 +630,4 @@ const exportSelectedPresets = async () => { opacity: 1; transform: scale(1) translateY(0); } - \ No newline at end of file + diff --git a/src/components/features/clients/ClientCard.vue b/src/components/features/clients/ClientCard.vue index 9d79ca2b..a941a554 100644 --- a/src/components/features/clients/ClientCard.vue +++ b/src/components/features/clients/ClientCard.vue @@ -1,39 +1,26 @@ diff --git a/src/components/features/clients/ClientCardActions.vue b/src/components/features/clients/ClientCardActions.vue new file mode 100644 index 00000000..0ddbd713 --- /dev/null +++ b/src/components/features/clients/ClientCardActions.vue @@ -0,0 +1,138 @@ + + + + + diff --git a/src/components/features/clients/ClientCardDetails.vue b/src/components/features/clients/ClientCardDetails.vue new file mode 100644 index 00000000..212c7adc --- /dev/null +++ b/src/components/features/clients/ClientCardDetails.vue @@ -0,0 +1,519 @@ + + + + + diff --git a/src/components/features/clients/ClientComments.vue b/src/components/features/clients/ClientComments.vue new file mode 100644 index 00000000..497bfcb3 --- /dev/null +++ b/src/components/features/clients/ClientComments.vue @@ -0,0 +1,243 @@ + + + + + diff --git a/src/components/features/clients/ClientInfo.vue b/src/components/features/clients/ClientInfo.vue index a3aa51a9..356febd5 100644 --- a/src/components/features/clients/ClientInfo.vue +++ b/src/components/features/clients/ClientInfo.vue @@ -1,7 +1,7 @@ + + diff --git a/src/components/features/clients/ScreenshotViewer.vue b/src/components/features/clients/ScreenshotViewer.vue new file mode 100644 index 00000000..d12e83b8 --- /dev/null +++ b/src/components/features/clients/ScreenshotViewer.vue @@ -0,0 +1,615 @@ + + + + + diff --git a/src/components/features/download/DownloadProgress.vue b/src/components/features/download/DownloadProgress.vue index d680e1ff..64ae6545 100644 --- a/src/components/features/download/DownloadProgress.vue +++ b/src/components/features/download/DownloadProgress.vue @@ -1,8 +1,8 @@ diff --git a/src/components/features/friends/BlockedUserCard.vue b/src/components/features/friends/BlockedUserCard.vue index f27c7414..828fdcf6 100644 --- a/src/components/features/friends/BlockedUserCard.vue +++ b/src/components/features/friends/BlockedUserCard.vue @@ -3,7 +3,10 @@
-
+
@@ -12,15 +15,18 @@ @{{ displayUsername }}

- {{ $t('common.blocked') }} + {{ $t("common.blocked") }}

-
@@ -29,11 +35,11 @@ diff --git a/src/components/features/friends/FriendCard.vue b/src/components/features/friends/FriendCard.vue index 95d1f40e..66dd0c1c 100644 --- a/src/components/features/friends/FriendCard.vue +++ b/src/components/features/friends/FriendCard.vue @@ -1,14 +1,19 @@ diff --git a/src/components/modals/clients/InsecureClientWarningModal.vue b/src/components/modals/clients/InsecureClientWarningModal.vue index 98b6e1c3..e2012cfb 100644 --- a/src/components/modals/clients/InsecureClientWarningModal.vue +++ b/src/components/modals/clients/InsecureClientWarningModal.vue @@ -1,13 +1,15 @@ diff --git a/src/components/modals/clients/LogViewerModal.vue b/src/components/modals/clients/LogViewerModal.vue index 73aa066e..bfb98268 100644 --- a/src/components/modals/clients/LogViewerModal.vue +++ b/src/components/modals/clients/LogViewerModal.vue @@ -1,68 +1,108 @@ diff --git a/src/components/modals/clients/TelemetryConsentModal.vue b/src/components/modals/clients/TelemetryConsentModal.vue index 08e4d9bb..094ad7ee 100644 --- a/src/components/modals/clients/TelemetryConsentModal.vue +++ b/src/components/modals/clients/TelemetryConsentModal.vue @@ -1,34 +1,42 @@ diff --git a/src/components/modals/common/FullscreenAvatarModal.vue b/src/components/modals/common/FullscreenAvatarModal.vue index 7ddc326c..4deae7a4 100644 --- a/src/components/modals/common/FullscreenAvatarModal.vue +++ b/src/components/modals/common/FullscreenAvatarModal.vue @@ -1,8 +1,14 @@