diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 6514857..8b438f4 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -github: 0pandadev +github: 0pandadev diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index b7740ca..e6d3ac7 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,75 +1,75 @@ -name: "\U0001F41E Bug report" -description: Create a report to help me improve Qopy -labels: [Bug] -assignees: - - 0PandaDEV -body: - # - - type: markdown - attributes: - value: | - Thanks for taking the time to fill out this bug report! - # - - type: textarea - id: description - attributes: - label: Describe the bug - description: A clear and concise description of what the bug is. - validations: - required: true - - - type: textarea - id: reproduce - attributes: - label: Steps to reproduce - description: Steps to reproduce the behavior - value: | - 1. Go to '...' - 2. Click on '....' - 3. Scroll down to '....' - 4. See error - validations: - required: true - - - type: textarea - id: expected - attributes: - label: Expected behavior - description: A clear and concise description of what you expected to happen. - validations: - required: true - - - type: textarea - id: screenshots - attributes: - label: Screenshots - description: If applicable, add screenshots to help explain your problem. - validations: - required: false - - - type: dropdown - id: os - attributes: - label: Operating system - options: - - Windows - - Linux - - macOS - validations: - required: true - - - type: input - id: version - attributes: - label: Version of Qopy - placeholder: e.g. 0.1.0 - validations: - required: true - - - type: textarea - id: additional - attributes: - label: Additional context - description: Add any other context about the problem here. - validations: - required: false +name: "\U0001F41E Bug report" +description: Create a report to help me improve Qopy +labels: [Bug] +assignees: + - 0PandaDEV +body: + # + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + # + - type: textarea + id: description + attributes: + label: Describe the bug + description: A clear and concise description of what the bug is. + validations: + required: true + + - type: textarea + id: reproduce + attributes: + label: Steps to reproduce + description: Steps to reproduce the behavior + value: | + 1. Go to '...' + 2. Click on '....' + 3. Scroll down to '....' + 4. See error + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected behavior + description: A clear and concise description of what you expected to happen. + validations: + required: true + + - type: textarea + id: screenshots + attributes: + label: Screenshots + description: If applicable, add screenshots to help explain your problem. + validations: + required: false + + - type: dropdown + id: os + attributes: + label: Operating system + options: + - Windows + - Linux + - macOS + validations: + required: true + + - type: input + id: version + attributes: + label: Version of Qopy + placeholder: e.g. 0.1.0 + validations: + required: true + + - type: textarea + id: additional + attributes: + label: Additional context + description: Add any other context about the problem here. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 7d2e94d..0cefcf6 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,19 +1,19 @@ -name: "\U0001F4A1 Feature request" -description: Suggest an idea for Qopy -labels: [Feature] -assignees: - - 0PandaDEV -body: - # - - type: markdown - attributes: - value: | - Thanks for taking the time to fill out this feature request! - # - - type: textarea - id: description - attributes: - label: Describe your requested feature - description: Give as many details as possible about your feature idea. - validations: - required: true +name: "\U0001F4A1 Feature request" +description: Suggest an idea for Qopy +labels: [Feature] +assignees: + - 0PandaDEV +body: + # + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this feature request! + # + - type: textarea + id: description + attributes: + label: Describe your requested feature + description: Give as many details as possible about your feature idea. + validations: + required: true diff --git a/.github/scripts/macOS.sh b/.github/scripts/macOS.sh index 0800a69..44e928a 100755 --- a/.github/scripts/macOS.sh +++ b/.github/scripts/macOS.sh @@ -1,40 +1,40 @@ -#!/bin/bash - -if [ -f .env ]; then - export $(cat .env | grep -v '^#' | xargs) -fi - -set -e - -required_vars=("APPLE_CERTIFICATE" "APPLE_CERTIFICATE_PASSWORD" "APPLE_ID" "APPLE_ID_PASSWORD" "KEYCHAIN_PASSWORD" "APP_BUNDLE_ID") -for var in "${required_vars[@]}"; do - if [ -z "${!var}" ]; then - exit 1 - fi -done - -bun run tauri build - -rm -f certificate.p12 -echo "$APPLE_CERTIFICATE" | base64 --decode > certificate.p12 2>/dev/null -security import certificate.p12 -P "$APPLE_CERTIFICATE_PASSWORD" -A 2>/dev/null - -SIGNING_IDENTITY=$(security find-identity -v -p codesigning | grep "Apple Development" | head -1 | awk -F '"' '{print $2}') - -if [ -z "$SIGNING_IDENTITY" ]; then - exit 1 -fi - -codesign --force --options runtime --sign "$SIGNING_IDENTITY" src-tauri/target/release/bundle/macos/*.app 2>/dev/null - -rm -f certificate.p12 - -hdiutil create -volname "Qopy" -srcfolder src-tauri/target/release/bundle/dmg -ov -format UDZO Qopy.dmg - -codesign --force --sign "$APPLE_CERTIFICATE" Qopy.dmg 2>/dev/null - -xcrun notarytool submit Qopy.dmg --apple-id "$APPLE_ID" --password "$APPLE_ID_PASSWORD" --team-id "$APPLE_CERTIFICATE" --wait - -xcrun stapler staple Qopy.dmg - -exit 0 +#!/bin/bash + +if [ -f .env ]; then + export $(cat .env | grep -v '^#' | xargs) +fi + +set -e + +required_vars=("APPLE_CERTIFICATE" "APPLE_CERTIFICATE_PASSWORD" "APPLE_ID" "APPLE_ID_PASSWORD" "KEYCHAIN_PASSWORD" "APP_BUNDLE_ID") +for var in "${required_vars[@]}"; do + if [ -z "${!var}" ]; then + exit 1 + fi +done + +bun run tauri build + +rm -f certificate.p12 +echo "$APPLE_CERTIFICATE" | base64 --decode > certificate.p12 2>/dev/null +security import certificate.p12 -P "$APPLE_CERTIFICATE_PASSWORD" -A 2>/dev/null + +SIGNING_IDENTITY=$(security find-identity -v -p codesigning | grep "Apple Development" | head -1 | awk -F '"' '{print $2}') + +if [ -z "$SIGNING_IDENTITY" ]; then + exit 1 +fi + +codesign --force --options runtime --sign "$SIGNING_IDENTITY" src-tauri/target/release/bundle/macos/*.app 2>/dev/null + +rm -f certificate.p12 + +hdiutil create -volname "Qopy" -srcfolder src-tauri/target/release/bundle/dmg -ov -format UDZO Qopy.dmg + +codesign --force --sign "$APPLE_CERTIFICATE" Qopy.dmg 2>/dev/null + +xcrun notarytool submit Qopy.dmg --apple-id "$APPLE_ID" --password "$APPLE_ID_PASSWORD" --team-id "$APPLE_CERTIFICATE" --wait + +xcrun stapler staple Qopy.dmg + +exit 0 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7e4cc80..c2777c0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,249 +1,249 @@ -name: "Nightly Builds" - -on: - push: - branches: - - main - pull_request: - branches: - - main - workflow_dispatch: - -jobs: - prepare: - runs-on: ubuntu-latest - outputs: - version: ${{ steps.get_version.outputs.VERSION }} - steps: - - uses: actions/checkout@v4 - - name: Get version - id: get_version - run: echo "VERSION=$(node -p "require('./src-tauri/tauri.conf.json').version")" >> $GITHUB_OUTPUT - - build-macos: - needs: prepare - runs-on: macos-latest - timeout-minutes: 30 - strategy: - matrix: - include: - - args: "--target aarch64-apple-darwin" - arch: "arm64" - - args: "--target x86_64-apple-darwin" - arch: "x64" - env: - APPLE_ID: ${{ secrets.APPLE_ID }} - APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} - TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} - steps: - - uses: actions/checkout@v4 - - name: Redact Sensitive Information - run: | - function redact_output { - sed -e "s/${{ secrets.APPLE_ID }}/REDACTED/g;s/${{ secrets.APPLE_ID_PASSWORD }}/REDACTED/g;s/${{ secrets.APPLE_CERTIFICATE }}/REDACTED/g;s/${{ secrets.APPLE_CERTIFICATE_PASSWORD }}/REDACTED/g;s/${{ secrets.KEYCHAIN_PASSWORD }}/REDACTED/g;s/${{ secrets.PAT }}/REDACTED/g;s/${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}/REDACTED/g" - } - exec > >(redact_output) 2>&1 - - uses: actions/setup-node@v4 - with: - node-version: 20 - - uses: dtolnay/rust-toolchain@stable - with: - targets: aarch64-apple-darwin,x86_64-apple-darwin - - uses: swatinem/rust-cache@v2 - with: - workspaces: "src-tauri -> target" - cache-directories: "~/.cargo/registry/index/,~/.cargo/registry/cache/,~/.cargo/git/db/" - shared-key: "macos-rust-cache" - save-if: "true" - - uses: actions/cache@v4 - with: - path: ~/.pnpm-store - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm- - - run: npm install -g pnpm && pnpm install - - name: Import Apple Developer Certificate - env: - APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} - APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} - run: | - echo $APPLE_CERTIFICATE | base64 --decode > certificate.p12 - security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain - security default-keychain -s build.keychain - security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain - security set-keychain-settings -lut 7200 build.keychain - security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign - security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain - security find-identity -v -p codesigning build.keychain - - name: Verify Certificate - run: | - CERT_INFO=$(security find-identity -v -p codesigning build.keychain | grep "Apple Development") - CERT_ID=$(echo "$CERT_INFO" | awk -F'"' '{print $2}') - echo "CERT_ID=$CERT_ID" >> $GITHUB_ENV - echo "Certificate imported." - - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} - APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} - TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - APPLE_SIGNING_IDENTITY: ${{ env.CERT_ID }} - with: - args: ${{ matrix.args }} - - name: Debug Signing Process - if: failure() - run: | - echo "Attempting manual signing:" - timeout 300 codesign --force --options runtime --sign "$CERT_ID" --entitlements src-tauri/entitlements.plist src-tauri/target/${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }}/release/bundle/macos/Qopy.app - echo "Verifying signature:" - codesign -dv --verbose=4 "src-tauri/target/${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }}/release/bundle/macos/Qopy.app" | sed 's/.*Authority=.*/Authority=REDACTED/' - - name: Set architecture label - run: | - if [[ "${{ matrix.args }}" == "--target aarch64-apple-darwin" ]]; then - echo "ARCH_LABEL=aarch64-apple-darwin" >> $GITHUB_ENV - else - echo "ARCH_LABEL=x86_64-apple-darwin" >> $GITHUB_ENV - fi - - name: Rename and Publish macOS Artifacts - run: | - mv src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/dmg/*.dmg src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/dmg/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.dmg - mv src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/macos/*.app.tar.gz src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/macos/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.app.tar.gz - mv src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/macos/*.app.tar.gz.sig src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/macos/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.app.tar.gz.sig - - uses: actions/upload-artifact@v4 - with: - name: macos-dmg-${{ matrix.arch }} - path: "src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/dmg/*.dmg" - - uses: actions/upload-artifact@v4 - with: - name: updater-macos-${{ matrix.arch }} - path: | - src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/macos/*.app.tar.gz - src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/macos/*.app.tar.gz.sig - - build-windows: - needs: prepare - strategy: - matrix: - include: - - args: "--target x86_64-pc-windows-msvc" - arch: "x64" - target: "x86_64-pc-windows-msvc" - - args: "--target aarch64-pc-windows-msvc" - arch: "arm64" - target: "aarch64-pc-windows-msvc" - runs-on: windows-latest - env: - TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20 - - uses: dtolnay/rust-toolchain@stable - with: - targets: x86_64-pc-windows-msvc,aarch64-pc-windows-msvc - - uses: swatinem/rust-cache@v2 - with: - workspaces: "src-tauri -> target" - cache-directories: "~/.cargo/registry/index/,~/.cargo/registry/cache/,~/.cargo/git/db/" - shared-key: "windows-rust-cache" - save-if: "true" - - uses: actions/cache@v4 - with: - path: ~/.pnpm-store - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm- - - run: npm install -g pnpm && pnpm install - - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - args: ${{ matrix.args }} - - name: List Bundle Directory - shell: pwsh - run: | - Write-Output "Checking build directories..." - Get-ChildItem -Path "src-tauri/target" -Recurse -Directory | Where-Object { $_.Name -eq "msi" } | ForEach-Object { - Write-Output "Found MSI directory: $($_.FullName)" - Get-ChildItem -Path $_.FullName -Filter "*.msi" | ForEach-Object { - Write-Output "Found MSI file: $($_.FullName)" - } - } - - name: Rename and Publish Windows Artifacts - run: | - mv src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi src-tauri/target/${{ matrix.target }}/release/bundle/msi/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.msi - mv src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi.sig src-tauri/target/${{ matrix.target }}/release/bundle/msi/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.msi.sig - - uses: actions/upload-artifact@v4 - with: - name: windows-${{ matrix.arch }} - path: src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi - - uses: actions/upload-artifact@v4 - with: - name: updater-windows-${{ matrix.arch }} - path: | - src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi - src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi.sig - - build-ubuntu: - needs: prepare - runs-on: ubuntu-latest - env: - TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20 - - uses: dtolnay/rust-toolchain@stable - with: - targets: x86_64-unknown-linux-gnu - - uses: swatinem/rust-cache@v2 - with: - workspaces: "src-tauri -> target" - cache-directories: "~/.cargo/registry/index/,~/.cargo/registry/cache/,~/.cargo/git/db/" - shared-key: "ubuntu-rust-cache" - save-if: "true" - - uses: actions/cache@v4 - with: - path: ~/.pnpm-store - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm- - - name: Install dependencies - run: | - sudo apt update - sudo apt install -y libwebkit2gtk-4.1-dev build-essential curl wget file libssl-dev libayatana-appindicator3-dev librsvg2-dev libasound2-dev rpm - echo "PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig" >> $GITHUB_ENV - - run: npm install -g pnpm && pnpm install - - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - args: --target x86_64-unknown-linux-gnu - - name: Rename Linux Artifacts - run: | - mv src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/deb/*.deb src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/deb/Qopy-${{ needs.prepare.outputs.version }}.deb - mv src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/*.AppImage src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}.AppImage - mv src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/*.AppImage.sig src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}.AppImage.sig - mv src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/*.rpm src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/Qopy-${{ needs.prepare.outputs.version }}.rpm - - uses: actions/upload-artifact@v4 - with: - name: ubuntu-deb - path: src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/deb/*.deb - - uses: actions/upload-artifact@v4 - with: - name: ubuntu-appimage - path: src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/*.AppImage - - uses: actions/upload-artifact@v4 - with: - name: ubuntu-rpm - path: src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/*.rpm - - uses: actions/upload-artifact@v4 - with: - name: updater-ubuntu - path: | - src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/*.AppImage +name: "Nightly Builds" + +on: + push: + branches: + - main + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + prepare: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.get_version.outputs.VERSION }} + steps: + - uses: actions/checkout@v4 + - name: Get version + id: get_version + run: echo "VERSION=$(node -p "require('./src-tauri/tauri.conf.json').version")" >> $GITHUB_OUTPUT + + build-macos: + needs: prepare + runs-on: macos-latest + timeout-minutes: 30 + strategy: + matrix: + include: + - args: "--target aarch64-apple-darwin" + arch: "arm64" + - args: "--target x86_64-apple-darwin" + arch: "x64" + env: + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + steps: + - uses: actions/checkout@v4 + - name: Redact Sensitive Information + run: | + function redact_output { + sed -e "s/${{ secrets.APPLE_ID }}/REDACTED/g;s/${{ secrets.APPLE_ID_PASSWORD }}/REDACTED/g;s/${{ secrets.APPLE_CERTIFICATE }}/REDACTED/g;s/${{ secrets.APPLE_CERTIFICATE_PASSWORD }}/REDACTED/g;s/${{ secrets.KEYCHAIN_PASSWORD }}/REDACTED/g;s/${{ secrets.PAT }}/REDACTED/g;s/${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}/REDACTED/g" + } + exec > >(redact_output) 2>&1 + - uses: actions/setup-node@v4 + with: + node-version: 20 + - uses: dtolnay/rust-toolchain@stable + with: + targets: aarch64-apple-darwin,x86_64-apple-darwin + - uses: swatinem/rust-cache@v2 + with: + workspaces: "src-tauri -> target" + cache-directories: "~/.cargo/registry/index/,~/.cargo/registry/cache/,~/.cargo/git/db/" + shared-key: "macos-rust-cache" + save-if: "true" + - uses: actions/cache@v4 + with: + path: ~/.pnpm-store + key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm- + - run: npm install -g pnpm && pnpm install + - name: Import Apple Developer Certificate + env: + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + run: | + echo $APPLE_CERTIFICATE | base64 --decode > certificate.p12 + security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain + security set-keychain-settings -lut 7200 build.keychain + security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain + security find-identity -v -p codesigning build.keychain + - name: Verify Certificate + run: | + CERT_INFO=$(security find-identity -v -p codesigning build.keychain | grep "Apple Development") + CERT_ID=$(echo "$CERT_INFO" | awk -F'"' '{print $2}') + echo "CERT_ID=$CERT_ID" >> $GITHUB_ENV + echo "Certificate imported." + - uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ env.CERT_ID }} + with: + args: ${{ matrix.args }} + - name: Debug Signing Process + if: failure() + run: | + echo "Attempting manual signing:" + timeout 300 codesign --force --options runtime --sign "$CERT_ID" --entitlements src-tauri/entitlements.plist src-tauri/target/${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }}/release/bundle/macos/Qopy.app + echo "Verifying signature:" + codesign -dv --verbose=4 "src-tauri/target/${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }}/release/bundle/macos/Qopy.app" | sed 's/.*Authority=.*/Authority=REDACTED/' + - name: Set architecture label + run: | + if [[ "${{ matrix.args }}" == "--target aarch64-apple-darwin" ]]; then + echo "ARCH_LABEL=aarch64-apple-darwin" >> $GITHUB_ENV + else + echo "ARCH_LABEL=x86_64-apple-darwin" >> $GITHUB_ENV + fi + - name: Rename and Publish macOS Artifacts + run: | + mv src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/dmg/*.dmg src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/dmg/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.dmg + mv src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/macos/*.app.tar.gz src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/macos/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.app.tar.gz + mv src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/macos/*.app.tar.gz.sig src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/macos/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.app.tar.gz.sig + - uses: actions/upload-artifact@v4 + with: + name: macos-dmg-${{ matrix.arch }} + path: "src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/dmg/*.dmg" + - uses: actions/upload-artifact@v4 + with: + name: updater-macos-${{ matrix.arch }} + path: | + src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/macos/*.app.tar.gz + src-tauri/target/${{ env.ARCH_LABEL }}/release/bundle/macos/*.app.tar.gz.sig + + build-windows: + needs: prepare + strategy: + matrix: + include: + - args: "--target x86_64-pc-windows-msvc" + arch: "x64" + target: "x86_64-pc-windows-msvc" + - args: "--target aarch64-pc-windows-msvc" + arch: "arm64" + target: "aarch64-pc-windows-msvc" + runs-on: windows-latest + env: + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + - uses: dtolnay/rust-toolchain@stable + with: + targets: x86_64-pc-windows-msvc,aarch64-pc-windows-msvc + - uses: swatinem/rust-cache@v2 + with: + workspaces: "src-tauri -> target" + cache-directories: "~/.cargo/registry/index/,~/.cargo/registry/cache/,~/.cargo/git/db/" + shared-key: "windows-rust-cache" + save-if: "true" + - uses: actions/cache@v4 + with: + path: ~/.pnpm-store + key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm- + - run: npm install -g pnpm && pnpm install + - uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: ${{ matrix.args }} + - name: List Bundle Directory + shell: pwsh + run: | + Write-Output "Checking build directories..." + Get-ChildItem -Path "src-tauri/target" -Recurse -Directory | Where-Object { $_.Name -eq "msi" } | ForEach-Object { + Write-Output "Found MSI directory: $($_.FullName)" + Get-ChildItem -Path $_.FullName -Filter "*.msi" | ForEach-Object { + Write-Output "Found MSI file: $($_.FullName)" + } + } + - name: Rename and Publish Windows Artifacts + run: | + mv src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi src-tauri/target/${{ matrix.target }}/release/bundle/msi/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.msi + mv src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi.sig src-tauri/target/${{ matrix.target }}/release/bundle/msi/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.msi.sig + - uses: actions/upload-artifact@v4 + with: + name: windows-${{ matrix.arch }} + path: src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi + - uses: actions/upload-artifact@v4 + with: + name: updater-windows-${{ matrix.arch }} + path: | + src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi + src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi.sig + + build-ubuntu: + needs: prepare + runs-on: ubuntu-latest + env: + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + - uses: dtolnay/rust-toolchain@stable + with: + targets: x86_64-unknown-linux-gnu + - uses: swatinem/rust-cache@v2 + with: + workspaces: "src-tauri -> target" + cache-directories: "~/.cargo/registry/index/,~/.cargo/registry/cache/,~/.cargo/git/db/" + shared-key: "ubuntu-rust-cache" + save-if: "true" + - uses: actions/cache@v4 + with: + path: ~/.pnpm-store + key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm- + - name: Install dependencies + run: | + sudo apt update + sudo apt install -y libwebkit2gtk-4.1-dev build-essential curl wget file libssl-dev libayatana-appindicator3-dev librsvg2-dev libasound2-dev rpm + echo "PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig" >> $GITHUB_ENV + - run: npm install -g pnpm && pnpm install + - uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: --target x86_64-unknown-linux-gnu + - name: Rename Linux Artifacts + run: | + mv src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/deb/*.deb src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/deb/Qopy-${{ needs.prepare.outputs.version }}.deb + mv src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/*.AppImage src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}.AppImage + mv src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/*.AppImage.sig src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}.AppImage.sig + mv src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/*.rpm src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/Qopy-${{ needs.prepare.outputs.version }}.rpm + - uses: actions/upload-artifact@v4 + with: + name: ubuntu-deb + path: src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/deb/*.deb + - uses: actions/upload-artifact@v4 + with: + name: ubuntu-appimage + path: src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/*.AppImage + - uses: actions/upload-artifact@v4 + with: + name: ubuntu-rpm + path: src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/*.rpm + - uses: actions/upload-artifact@v4 + with: + name: updater-ubuntu + path: | + src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/*.AppImage src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/*.AppImage.sig \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b3c8847..3a0e70a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,325 +1,325 @@ -name: "Release" - -on: - push: - tags: - - "v*" - workflow_dispatch: - -jobs: - prepare: - permissions: write-all - runs-on: ubuntu-latest - outputs: - version: ${{ steps.get_version.outputs.VERSION }} - steps: - - uses: actions/checkout@v4 - - name: Get version - id: get_version - run: | - VERSION=$(node -p 'require("./src-tauri/tauri.conf.json").version') - echo "VERSION=$VERSION" >> $GITHUB_OUTPUT - - build-macos: - permissions: write-all - needs: prepare - strategy: - matrix: - include: - - args: "--target aarch64-apple-darwin" - arch: "silicon" - - args: "--target x86_64-apple-darwin" - arch: "intel" - runs-on: macos-latest - env: - APPLE_ID: ${{ secrets.APPLE_ID }} - APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} - TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} - steps: - - uses: actions/checkout@v4 - - name: Redact Sensitive Information - run: | - function redact_output { - sed -e "s/${{ secrets.REDACT_PATTERN }}/REDACTED/g" - } - exec > >(redact_output) 2>&1 - - uses: actions/setup-node@v4 - with: - node-version: 20 - - uses: dtolnay/rust-toolchain@stable - with: - targets: aarch64-apple-darwin,x86_64-apple-darwin - - uses: swatinem/rust-cache@v2 - with: - workspaces: "src-tauri -> target" - cache-directories: "~/.cargo/registry/index/,~/.cargo/registry/cache/,~/.cargo/git/db/" - shared-key: "macos-rust-cache" - save-if: "true" - - uses: actions/cache@v4 - with: - path: ~/.pnpm-store - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm- - - run: npm install -g pnpm && pnpm install - - name: Import Apple Developer Certificate - env: - APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} - APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} - run: | - echo $APPLE_CERTIFICATE | base64 --decode > certificate.p12 - security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain - security default-keychain -s build.keychain - security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain - security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign - security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain - - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} - APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} - TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - with: - args: ${{ matrix.args }} - - - name: Rename macOS Artifacts - run: | - mv src-tauri/target/${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }}/release/bundle/dmg/*.dmg src-tauri/target/${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }}/release/bundle/dmg/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.dmg - - name: Upload artifacts - uses: actions/upload-artifact@v4 - with: - name: macos-${{ matrix.arch }}-binaries - path: | - src-tauri/target/**/release/bundle/dmg/*.dmg - - build-windows: - permissions: write-all - needs: prepare - strategy: - matrix: - include: - - args: "--target x86_64-pc-windows-msvc" - arch: "x64" - target: "x86_64-pc-windows-msvc" - - args: "--target aarch64-pc-windows-msvc" - arch: "arm64" - target: "aarch64-pc-windows-msvc" - runs-on: windows-latest - env: - TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20 - - uses: dtolnay/rust-toolchain@stable - with: - targets: x86_64-pc-windows-msvc,aarch64-pc-windows-msvc - - uses: swatinem/rust-cache@v2 - with: - workspaces: "src-tauri -> target" - cache-directories: "~/.cargo/registry/index/,~/.cargo/registry/cache/,~/.cargo/git/db/" - shared-key: "windows-rust-cache" - save-if: "true" - - uses: actions/cache@v4 - with: - path: ~/.pnpm-store - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm- - - run: npm install -g pnpm && pnpm install - - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - args: ${{ matrix.args }} - - name: List Bundle Directory - shell: pwsh - run: | - $bundlePath = "src-tauri/target/${{ matrix.target }}/release/bundle/msi" - if (Test-Path $bundlePath) { - Write-Output "Contents of ${bundlePath}:" - Get-ChildItem -Path $bundlePath - } else { - Write-Output "Path ${bundlePath} does not exist." - } - - name: Rename Windows Artifacts - shell: pwsh - run: | - $bundlePath = "src-tauri/target/${{ matrix.target }}/release/bundle/msi" - $version = "${{ needs.prepare.outputs.version }}" - $arch = "${{ matrix.arch }}" - if (Test-Path $bundlePath) { - $msiFiles = Get-ChildItem -Path "$bundlePath/*.msi" - foreach ($file in $msiFiles) { - $newName = "Qopy-$version`_$arch.msi" - Rename-Item -Path $file.FullName -NewName $newName - } - } else { - Write-Error "Path ${bundlePath} does not exist." - exit 1 - } - - name: Upload artifacts - uses: actions/upload-artifact@v4 - with: - name: windows-${{ matrix.arch }}-binaries - path: src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi - - build-linux: - permissions: write-all - needs: prepare - runs-on: ubuntu-latest - env: - TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: actions/setup-node@v4 - with: - node-version: 20 - - uses: dtolnay/rust-toolchain@stable - - uses: swatinem/rust-cache@v2 - with: - workspaces: "src-tauri -> target" - cache-directories: "~/.cargo/registry/index/,~/.cargo/registry/cache/,~/.cargo/git/db/" - shared-key: "linux-rust-cache" - save-if: "true" - - uses: actions/cache@v4 - with: - path: ~/.pnpm-store - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm- - - name: Install dependencies - run: | - sudo apt update - sudo apt install -y libwebkit2gtk-4.1-dev build-essential curl wget file libssl-dev libayatana-appindicator3-dev librsvg2-dev libasound2-dev rpm - echo "PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig" >> $GITHUB_ENV - - run: npm install -g pnpm && pnpm install - - name: Generate Changelog - id: changelog - run: | - CHANGELOG=$(git log $(git describe --tags --abbrev=0)..HEAD --pretty=format:"- %s") - echo "CHANGELOG<> $GITHUB_ENV - echo "$CHANGELOG" >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV - - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - args: --target x86_64-unknown-linux-gnu - - name: Rename Linux Artifacts - run: | - mv src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/deb/*.deb src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/deb/Qopy-${{ needs.prepare.outputs.version }}.deb - mv src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/*.AppImage src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}.AppImage - mv src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/*.rpm src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/Qopy-${{ needs.prepare.outputs.version }}.rpm - - name: Upload artifacts - uses: actions/upload-artifact@v4 - with: - name: linux-binaries - path: | - src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/deb/*.deb - src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/*.AppImage - src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/*.rpm - - create-release: - permissions: write-all - needs: [prepare, build-macos, build-windows, build-linux] - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - token: ${{ secrets.PAT }} - - - name: Check if release already exists - id: check_release - run: | - VERSION="${{ needs.prepare.outputs.version }}" - RELEASE_EXISTS=$(gh release view v$VERSION --json id --jq '.id' 2>/dev/null || echo "") - if [ -n "$RELEASE_EXISTS" ]; then - echo "SKIP_RELEASE=true" >> $GITHUB_ENV - else - echo "SKIP_RELEASE=false" >> $GITHUB_ENV - fi - env: - GITHUB_TOKEN: ${{ secrets.PAT }} - - - name: Download all artifacts - if: env.SKIP_RELEASE == 'false' - uses: actions/download-artifact@v4 - with: - path: artifacts - - - name: Update CHANGELOG - if: env.SKIP_RELEASE == 'false' - id: changelog - uses: requarks/changelog-action@v1 - with: - token: ${{ github.token }} - tag: ${{ github.ref_name }} - - - name: Generate Release Body - if: env.SKIP_RELEASE == 'false' - id: release_body - run: | - VERSION="${{ needs.prepare.outputs.version }}" - - # Calculate hashes with corrected paths - WINDOWS_ARM_HASH=$(sha256sum "artifacts/windows-arm64-binaries/Qopy-${VERSION}_arm64.msi" | awk '{ print $1 }') - WINDOWS_64_HASH=$(sha256sum "artifacts/windows-x64-binaries/Qopy-${VERSION}_x64.msi" | awk '{ print $1 }') - MAC_SILICON_HASH=$(sha256sum "artifacts/macos-silicon-binaries/aarch64-apple-darwin/release/bundle/dmg/Qopy-${VERSION}_silicon.dmg" | awk '{ print $1 }') - MAC_INTEL_HASH=$(sha256sum "artifacts/macos-intel-binaries/x86_64-apple-darwin/release/bundle/dmg/Qopy-${VERSION}_intel.dmg" | awk '{ print $1 }') - DEBIAN_HASH=$(sha256sum "artifacts/linux-binaries/deb/Qopy-${VERSION}.deb" | awk '{ print $1 }') - APPIMAGE_HASH=$(sha256sum "artifacts/linux-binaries/appimage/Qopy-${VERSION}.AppImage" | awk '{ print $1 }') - REDHAT_HASH=$(sha256sum "artifacts/linux-binaries/rpm/Qopy-${VERSION}.rpm" | awk '{ print $1 }') - - # Debug output - echo "Calculated hashes:" - echo "Windows ARM: $WINDOWS_ARM_HASH" - echo "Windows x64: $WINDOWS_64_HASH" - echo "Mac Silicon: $MAC_SILICON_HASH" - echo "Mac Intel: $MAC_INTEL_HASH" - echo "Debian: $DEBIAN_HASH" - echo "AppImage: $APPIMAGE_HASH" - echo "Red Hat: $REDHAT_HASH" - - RELEASE_BODY=$(cat <<-EOF - - ${{ needs.create-release.outputs.changelog }} - - ## ⬇️ Downloads - - - [Windows (x64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_x64.msi) - ${WINDOWS_64_HASH} - - [Windows (ARM64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_arm64.msi) - ${WINDOWS_ARM_HASH} - - [macOS (Silicon)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_silicon.dmg) - ${MAC_SILICON_HASH} - - [macOS (Intel)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_intel.dmg) - ${MAC_INTEL_HASH} - - [Debian](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}.deb) - ${DEBIAN_HASH} - - [AppImage](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}.AppImage) - ${APPIMAGE_HASH} - - [Red Hat](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}.rpm) - ${REDHAT_HASH} - EOF - ) - - echo "RELEASE_BODY<> $GITHUB_ENV - echo "$RELEASE_BODY" >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV - - - name: Create Release - if: env.SKIP_RELEASE == 'false' - uses: softprops/action-gh-release@v2 - env: - GITHUB_TOKEN: ${{ secrets.PAT }} - with: - draft: true - tag_name: v${{ needs.prepare.outputs.version }} - name: v${{ needs.prepare.outputs.version }} - files: | - artifacts/**/*.dmg - artifacts/**/*.msi - artifacts/**/*.deb - artifacts/**/*.AppImage - artifacts/**/*.rpm +name: "Release" + +on: + push: + tags: + - "v*" + workflow_dispatch: + +jobs: + prepare: + permissions: write-all + runs-on: ubuntu-latest + outputs: + version: ${{ steps.get_version.outputs.VERSION }} + steps: + - uses: actions/checkout@v4 + - name: Get version + id: get_version + run: | + VERSION=$(node -p 'require("./src-tauri/tauri.conf.json").version') + echo "VERSION=$VERSION" >> $GITHUB_OUTPUT + + build-macos: + permissions: write-all + needs: prepare + strategy: + matrix: + include: + - args: "--target aarch64-apple-darwin" + arch: "silicon" + - args: "--target x86_64-apple-darwin" + arch: "intel" + runs-on: macos-latest + env: + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + steps: + - uses: actions/checkout@v4 + - name: Redact Sensitive Information + run: | + function redact_output { + sed -e "s/${{ secrets.REDACT_PATTERN }}/REDACTED/g" + } + exec > >(redact_output) 2>&1 + - uses: actions/setup-node@v4 + with: + node-version: 20 + - uses: dtolnay/rust-toolchain@stable + with: + targets: aarch64-apple-darwin,x86_64-apple-darwin + - uses: swatinem/rust-cache@v2 + with: + workspaces: "src-tauri -> target" + cache-directories: "~/.cargo/registry/index/,~/.cargo/registry/cache/,~/.cargo/git/db/" + shared-key: "macos-rust-cache" + save-if: "true" + - uses: actions/cache@v4 + with: + path: ~/.pnpm-store + key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm- + - run: npm install -g pnpm && pnpm install + - name: Import Apple Developer Certificate + env: + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + run: | + echo $APPLE_CERTIFICATE | base64 --decode > certificate.p12 + security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain + security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain + - uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + with: + args: ${{ matrix.args }} + + - name: Rename macOS Artifacts + run: | + mv src-tauri/target/${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }}/release/bundle/dmg/*.dmg src-tauri/target/${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }}/release/bundle/dmg/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.dmg + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: macos-${{ matrix.arch }}-binaries + path: | + src-tauri/target/**/release/bundle/dmg/*.dmg + + build-windows: + permissions: write-all + needs: prepare + strategy: + matrix: + include: + - args: "--target x86_64-pc-windows-msvc" + arch: "x64" + target: "x86_64-pc-windows-msvc" + - args: "--target aarch64-pc-windows-msvc" + arch: "arm64" + target: "aarch64-pc-windows-msvc" + runs-on: windows-latest + env: + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + - uses: dtolnay/rust-toolchain@stable + with: + targets: x86_64-pc-windows-msvc,aarch64-pc-windows-msvc + - uses: swatinem/rust-cache@v2 + with: + workspaces: "src-tauri -> target" + cache-directories: "~/.cargo/registry/index/,~/.cargo/registry/cache/,~/.cargo/git/db/" + shared-key: "windows-rust-cache" + save-if: "true" + - uses: actions/cache@v4 + with: + path: ~/.pnpm-store + key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm- + - run: npm install -g pnpm && pnpm install + - uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: ${{ matrix.args }} + - name: List Bundle Directory + shell: pwsh + run: | + $bundlePath = "src-tauri/target/${{ matrix.target }}/release/bundle/msi" + if (Test-Path $bundlePath) { + Write-Output "Contents of ${bundlePath}:" + Get-ChildItem -Path $bundlePath + } else { + Write-Output "Path ${bundlePath} does not exist." + } + - name: Rename Windows Artifacts + shell: pwsh + run: | + $bundlePath = "src-tauri/target/${{ matrix.target }}/release/bundle/msi" + $version = "${{ needs.prepare.outputs.version }}" + $arch = "${{ matrix.arch }}" + if (Test-Path $bundlePath) { + $msiFiles = Get-ChildItem -Path "$bundlePath/*.msi" + foreach ($file in $msiFiles) { + $newName = "Qopy-$version`_$arch.msi" + Rename-Item -Path $file.FullName -NewName $newName + } + } else { + Write-Error "Path ${bundlePath} does not exist." + exit 1 + } + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: windows-${{ matrix.arch }}-binaries + path: src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi + + build-linux: + permissions: write-all + needs: prepare + runs-on: ubuntu-latest + env: + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-node@v4 + with: + node-version: 20 + - uses: dtolnay/rust-toolchain@stable + - uses: swatinem/rust-cache@v2 + with: + workspaces: "src-tauri -> target" + cache-directories: "~/.cargo/registry/index/,~/.cargo/registry/cache/,~/.cargo/git/db/" + shared-key: "linux-rust-cache" + save-if: "true" + - uses: actions/cache@v4 + with: + path: ~/.pnpm-store + key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm- + - name: Install dependencies + run: | + sudo apt update + sudo apt install -y libwebkit2gtk-4.1-dev build-essential curl wget file libssl-dev libayatana-appindicator3-dev librsvg2-dev libasound2-dev rpm + echo "PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig" >> $GITHUB_ENV + - run: npm install -g pnpm && pnpm install + - name: Generate Changelog + id: changelog + run: | + CHANGELOG=$(git log $(git describe --tags --abbrev=0)..HEAD --pretty=format:"- %s") + echo "CHANGELOG<> $GITHUB_ENV + echo "$CHANGELOG" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + - uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: --target x86_64-unknown-linux-gnu + - name: Rename Linux Artifacts + run: | + mv src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/deb/*.deb src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/deb/Qopy-${{ needs.prepare.outputs.version }}.deb + mv src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/*.AppImage src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}.AppImage + mv src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/*.rpm src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/Qopy-${{ needs.prepare.outputs.version }}.rpm + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: linux-binaries + path: | + src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/deb/*.deb + src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/appimage/*.AppImage + src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/*.rpm + + create-release: + permissions: write-all + needs: [prepare, build-macos, build-windows, build-linux] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.PAT }} + + - name: Check if release already exists + id: check_release + run: | + VERSION="${{ needs.prepare.outputs.version }}" + RELEASE_EXISTS=$(gh release view v$VERSION --json id --jq '.id' 2>/dev/null || echo "") + if [ -n "$RELEASE_EXISTS" ]; then + echo "SKIP_RELEASE=true" >> $GITHUB_ENV + else + echo "SKIP_RELEASE=false" >> $GITHUB_ENV + fi + env: + GITHUB_TOKEN: ${{ secrets.PAT }} + + - name: Download all artifacts + if: env.SKIP_RELEASE == 'false' + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Update CHANGELOG + if: env.SKIP_RELEASE == 'false' + id: changelog + uses: requarks/changelog-action@v1 + with: + token: ${{ github.token }} + tag: ${{ github.ref_name }} + + - name: Generate Release Body + if: env.SKIP_RELEASE == 'false' + id: release_body + run: | + VERSION="${{ needs.prepare.outputs.version }}" + + # Calculate hashes with corrected paths + WINDOWS_ARM_HASH=$(sha256sum "artifacts/windows-arm64-binaries/Qopy-${VERSION}_arm64.msi" | awk '{ print $1 }') + WINDOWS_64_HASH=$(sha256sum "artifacts/windows-x64-binaries/Qopy-${VERSION}_x64.msi" | awk '{ print $1 }') + MAC_SILICON_HASH=$(sha256sum "artifacts/macos-silicon-binaries/aarch64-apple-darwin/release/bundle/dmg/Qopy-${VERSION}_silicon.dmg" | awk '{ print $1 }') + MAC_INTEL_HASH=$(sha256sum "artifacts/macos-intel-binaries/x86_64-apple-darwin/release/bundle/dmg/Qopy-${VERSION}_intel.dmg" | awk '{ print $1 }') + DEBIAN_HASH=$(sha256sum "artifacts/linux-binaries/deb/Qopy-${VERSION}.deb" | awk '{ print $1 }') + APPIMAGE_HASH=$(sha256sum "artifacts/linux-binaries/appimage/Qopy-${VERSION}.AppImage" | awk '{ print $1 }') + REDHAT_HASH=$(sha256sum "artifacts/linux-binaries/rpm/Qopy-${VERSION}.rpm" | awk '{ print $1 }') + + # Debug output + echo "Calculated hashes:" + echo "Windows ARM: $WINDOWS_ARM_HASH" + echo "Windows x64: $WINDOWS_64_HASH" + echo "Mac Silicon: $MAC_SILICON_HASH" + echo "Mac Intel: $MAC_INTEL_HASH" + echo "Debian: $DEBIAN_HASH" + echo "AppImage: $APPIMAGE_HASH" + echo "Red Hat: $REDHAT_HASH" + + RELEASE_BODY=$(cat <<-EOF + + ${{ needs.create-release.outputs.changelog }} + + ## ⬇️ Downloads + + - [Windows (x64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_x64.msi) - ${WINDOWS_64_HASH} + - [Windows (ARM64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_arm64.msi) - ${WINDOWS_ARM_HASH} + - [macOS (Silicon)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_silicon.dmg) - ${MAC_SILICON_HASH} + - [macOS (Intel)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_intel.dmg) - ${MAC_INTEL_HASH} + - [Debian](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}.deb) - ${DEBIAN_HASH} + - [AppImage](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}.AppImage) - ${APPIMAGE_HASH} + - [Red Hat](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}.rpm) - ${REDHAT_HASH} + EOF + ) + + echo "RELEASE_BODY<> $GITHUB_ENV + echo "$RELEASE_BODY" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + + - name: Create Release + if: env.SKIP_RELEASE == 'false' + uses: softprops/action-gh-release@v2 + env: + GITHUB_TOKEN: ${{ secrets.PAT }} + with: + draft: true + tag_name: v${{ needs.prepare.outputs.version }} + name: v${{ needs.prepare.outputs.version }} + files: | + artifacts/**/*.dmg + artifacts/**/*.msi + artifacts/**/*.deb + artifacts/**/*.AppImage + artifacts/**/*.rpm body: ${{ env.RELEASE_BODY }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 26109c1..7d3ac00 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,26 @@ -# Nuxt dev/build outputs -.output -.data -.nuxt -.nitro -.cache -dist - -# Node dependencies -node_modules - -# Logs -logs -*.log - -# Misc -.DS_Store -.fleet -.idea - -# Local env files -.env -.env.* -!.env.example -.gitignore -.vscode \ No newline at end of file +# Nuxt dev/build outputs +.output +.data +.nuxt +.nitro +.cache +dist + +# Node dependencies +node_modules + +# Logs +logs +*.log + +# Misc +.DS_Store +.fleet +.idea + +# Local env files +.env +.env.* +!.env.example +.gitignore +.vscode diff --git a/GET_STARTED.md b/GET_STARTED.md index a793041..2053ca5 100644 --- a/GET_STARTED.md +++ b/GET_STARTED.md @@ -1,23 +1,23 @@ -# Get Started - -The default hotkey for Qopy is Windows+V which is also the hotkey for the default clipboard manager to turn that off follow [this guide](https://github.com/0PandaDEV/Qopy/blob/main/GET_STARTED.md#disable-windowsv-for-default-clipboard-manager). - -All the data of Qopy is stored inside of a SQLite database. - -| Operating System | Path | -|------------------|-----------------------------------------------------------------| -| Windows | `C:\Users\USERNAME\AppData\Roaming\net.pandadev.qopy` | -| macOS | `/Users/USERNAME/Library/Application Support/net.pandadev.qopy` | -| Linux | `/home/USERNAME/.local/share/net.pandadev.qopy` | - -## Disable Windows+V for default clipboard manager - - - -To disable the default clipboard manager popup from windows open Command prompt and run this command - -```cmd -reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\System" /v AllowClipboardHistory /t REG_DWORD /d 0 /f -``` - -After that a restart may be reqired. +# Get Started + +The default hotkey for Qopy is Windows+V which is also the hotkey for the default clipboard manager to turn that off follow [this guide](https://github.com/0PandaDEV/Qopy/blob/main/GET_STARTED.md#disable-windowsv-for-default-clipboard-manager). + +All the data of Qopy is stored inside of a SQLite database. + +| Operating System | Path | +|------------------|-----------------------------------------------------------------| +| Windows | `C:\Users\USERNAME\AppData\Roaming\net.pandadev.qopy` | +| macOS | `/Users/USERNAME/Library/Application Support/net.pandadev.qopy` | +| Linux | `/home/USERNAME/.local/share/net.pandadev.qopy` | + +## Disable Windows+V for default clipboard manager + + + +To disable the default clipboard manager popup from windows open Command prompt and run this command + +```cmd +reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\System" /v AllowClipboardHistory /t REG_DWORD /d 0 /f +``` + +After that a restart may be reqired. diff --git a/LICENSE b/LICENSE index 0ad25db..ada1a81 100644 --- a/LICENSE +++ b/LICENSE @@ -1,661 +1,661 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/README.md b/README.md index 0caf872..ca21042 100644 --- a/README.md +++ b/README.md @@ -1,129 +1,129 @@ -
- - -

Qopy

- -The fixed and simple clipboard manager for both Windows and Linux. - - - Windows (x64) - -• - - Windows (arm64) - -
- - Linux (deb) - -• - - Linux (rpm) - -• - - Linux (AppImage) - -
- - macOS (Silicon) - -• - - macOS (Intel) - -
-
-Nightly releases can be found here - -
- -[discord »](https://discord.gg/invite/Y7SbYphVw9) - -> \[!IMPORTANT] -> -> **Star this project**, You will receive all release notifications from GitHub without any delay \~ ⭐️ - -
- Star History - - - - - -
- -[![wakatime](https://wakatime.com/badge/user/018ce503-097f-4057-9599-db20b190920c/project/fe76359d-56c2-4a13-8413-55207b6ad298.svg?style=flat_square)](https://wakatime.com/badge/user/018ce503-097f-4057-9599-db20b190920c/project/fe76359d-56c2-4a13-8413-55207b6ad298) - -## 📋 What is Qopy - -Qopy is a fixed clipboard manager designed as a simple alternative to the standard clipboard on Windows. It aims to provide a faster, more reliable experience while providing an extensive set of features compared to its Windows counterpart. - -## 🚧 Roadmap -- [x] [Setup guide](https://github.com/0PandaDEV/Qopy/blob/main/GET_STARTED.md) -- [ ] Sync Clipboard across devices https://github.com/0PandaDEV/Qopy/issues/8 -- [x] Settings https://github.com/0PandaDEV/Qopy/issues/2 -- [x] Metadata for copied items https://github.com/0PandaDEV/Qopy/issues/5 -- [ ] Code highlighting https://github.com/0PandaDEV/Qopy/issues/7 -- [ ] Streamshare integration https://github.com/0PandaDEV/Qopy/issues/4 -- [ ] Content type filter https://github.com/0PandaDEV/Qopy/issues/16 -- [ ] Preview for copied files https://github.com/0PandaDEV/Qopy/issues/15 -- [ ] Convert files to other formats https://github.com/0PandaDEV/Qopy/issues/17 -- [x] Option for custom keybind https://github.com/0PandaDEV/Qopy/issues/3 -- [x] macOS Support https://github.com/0PandaDEV/Qopy/issues/13 - -If you have ideas for features to include, please write a feature request [here](https://github.com/0pandadev/Qopy/issues). - -## 📦 Concepts - -Here you can see a few concepts these might not be implemented: - -![Clipboard](https://github.com/user-attachments/assets/45a44a13-6ebd-4f2d-84d2-55178e303a54) -![Settings](https://github.com/user-attachments/assets/bff5456a-f413-4e62-a43d-22c8e453aa87) - - -## ❤️ Donations & Support - -Qopy is open-source and free to use. I appreciate donations to support ongoing development and improvements. Your contributions are voluntary and help me enhance the app for everyone. - - - -## ⌨️ Local development - -You can use GitHub Codespaces for online development: - -[![][codespaces-shield]][codespaces-link] - -Or to get Qopy set up on your machine, you'll need to have Rust and bun installed. Then, follow these steps: - -```zsh -git clone https://github.com/0pandadev/Qopy.git -cd Qopy -bun i -bun dev -``` - -> \[!TIP] -> -> If you are interested in contributing code, feel free to check out the [Issues](https://github.com/0pandadev/Qopy/issues) section. - -## 🔨 Building for production - -To build for production simply execute: - -```zsh -bun build -``` - -> \[!NOTE] -> -> Don't worry, it will fail at the end because it can not detect a Private key, but the installer files will be generated regardless of that. -> -> You can find them in `src-tauri/target/release/bundle`. - -## 📝 License - -Qopy is licensed under AGPL-3. See the [LICENSE file](./LICENCE) for more information. - -[codespaces-link]: https://codespaces.new/0pandadev/Qopy -[codespaces-shield]: https://github.com/codespaces/badge.svg +
+ + +

Qopy

+ +The fixed and simple clipboard manager for both Windows and Linux. + + + Windows (x64) + +• + + Windows (arm64) + +
+ + Linux (deb) + +• + + Linux (rpm) + +• + + Linux (AppImage) + +
+ + macOS (Silicon) + +• + + macOS (Intel) + +
+
+Nightly releases can be found here + +
+ +[discord »](https://discord.gg/invite/Y7SbYphVw9) + +> \[!IMPORTANT] +> +> **Star this project**, You will receive all release notifications from GitHub without any delay \~ ⭐️ + +
+ Star History + + + + + +
+ +[![wakatime](https://wakatime.com/badge/user/018ce503-097f-4057-9599-db20b190920c/project/fe76359d-56c2-4a13-8413-55207b6ad298.svg?style=flat_square)](https://wakatime.com/badge/user/018ce503-097f-4057-9599-db20b190920c/project/fe76359d-56c2-4a13-8413-55207b6ad298) + +## 📋 What is Qopy + +Qopy is a fixed clipboard manager designed as a simple alternative to the standard clipboard on Windows. It aims to provide a faster, more reliable experience while providing an extensive set of features compared to its Windows counterpart. + +## 🚧 Roadmap +- [x] [Setup guide](https://github.com/0PandaDEV/Qopy/blob/main/GET_STARTED.md) +- [ ] Sync Clipboard across devices https://github.com/0PandaDEV/Qopy/issues/8 +- [x] Settings https://github.com/0PandaDEV/Qopy/issues/2 +- [x] Metadata for copied items https://github.com/0PandaDEV/Qopy/issues/5 +- [ ] Code highlighting https://github.com/0PandaDEV/Qopy/issues/7 +- [ ] Streamshare integration https://github.com/0PandaDEV/Qopy/issues/4 +- [ ] Content type filter https://github.com/0PandaDEV/Qopy/issues/16 +- [ ] Preview for copied files https://github.com/0PandaDEV/Qopy/issues/15 +- [ ] Convert files to other formats https://github.com/0PandaDEV/Qopy/issues/17 +- [x] Option for custom keybind https://github.com/0PandaDEV/Qopy/issues/3 +- [x] macOS Support https://github.com/0PandaDEV/Qopy/issues/13 + +If you have ideas for features to include, please write a feature request [here](https://github.com/0pandadev/Qopy/issues). + +## 📦 Concepts + +Here you can see a few concepts these might not be implemented: + +![Clipboard](https://github.com/user-attachments/assets/45a44a13-6ebd-4f2d-84d2-55178e303a54) +![Settings](https://github.com/user-attachments/assets/bff5456a-f413-4e62-a43d-22c8e453aa87) + + +## ❤️ Donations & Support + +Qopy is open-source and free to use. I appreciate donations to support ongoing development and improvements. Your contributions are voluntary and help me enhance the app for everyone. + + + +## ⌨️ Local development + +You can use GitHub Codespaces for online development: + +[![][codespaces-shield]][codespaces-link] + +Or to get Qopy set up on your machine, you'll need to have Rust and bun installed. Then, follow these steps: + +```zsh +git clone https://github.com/0pandadev/Qopy.git +cd Qopy +bun i +bun dev +``` + +> \[!TIP] +> +> If you are interested in contributing code, feel free to check out the [Issues](https://github.com/0pandadev/Qopy/issues) section. + +## 🔨 Building for production + +To build for production simply execute: + +```zsh +bun build +``` + +> \[!NOTE] +> +> Don't worry, it will fail at the end because it can not detect a Private key, but the installer files will be generated regardless of that. +> +> You can find them in `src-tauri/target/release/bundle`. + +## 📝 License + +Qopy is licensed under AGPL-3. See the [LICENSE file](./LICENCE) for more information. + +[codespaces-link]: https://codespaces.new/0pandadev/Qopy +[codespaces-shield]: https://github.com/codespaces/badge.svg diff --git a/README_ru.md b/README_ru.md index e9f63ad..65c577f 100644 --- a/README_ru.md +++ b/README_ru.md @@ -1,130 +1,130 @@ -
- - -

Qopy

- -Простой и исправленный менеджер буфера обмена как для Windows, так и для Linux. - - - Windows (x64) - -• - - Windows (arm64) - -
- - Linux (deb) - -• - - Linux (rpm) - -• - - Linux (AppImage) - -
- - macOS (Silicon) - -• - - macOS (Intel) - -
-
-Тестовые версии можно найти тут - -
- -[discord »](https://discord.gg/invite/Y7SbYphVw9) - -> \[!IMPORTANT] -> -> **Нажав на звезду**, Вы будете получать все уведомления от Github о новых версиях без задержек \~ ⭐️ - -
- Star History - - - - - - -
- -[![wakatime](https://wakatime.com/badge/user/018ce503-097f-4057-9599-db20b190920c/project/fe76359d-56c2-4a13-8413-55207b6ad298.svg?style=flat_square)](https://wakatime.com/badge/user/018ce503-097f-4057-9599-db20b190920c/project/fe76359d-56c2-4a13-8413-55207b6ad298) - -## 📋 Что такое Qopy - -Qopy представляет собой исправленный менеджер буфера обмена, разработанный как простая альтернатива стандартному буферу обмена в Windows. Его цель - обеспечить более быструю и надежную работу, предоставляя при этом обширный набор функций по сравнению со своим аналогом в Windows. - -## 🚧 Дорожная карта -- [ ] [Руководство по установке](https://github.com/0PandaDEV/Qopy/blob/main/GET_STARTED.md) -- [ ] Синхронизация буфера обмена между устройствами https://github.com/0PandaDEV/Qopy/issues/8 -- [ ] Настройки https://github.com/0PandaDEV/Qopy/issues/2 -- [x] Метаданные для скопированных элементов https://github.com/0PandaDEV/Qopy/issues/5 -- [ ] Выделение кода https://github.com/0PandaDEV/Qopy/issues/7 -- [ ] Интеграция Streamshare https://github.com/0PandaDEV/Qopy/issues/4 -- [ ] Фильтр типов контента https://github.com/0PandaDEV/Qopy/issues/16 -- [ ] Превью для скопированных файлов https://github.com/0PandaDEV/Qopy/issues/15 -- [ ] Конвертация файлов в другие форматы https://github.com/0PandaDEV/Qopy/issues/17 -- [x] Опция для пользовательской привязки клавиш https://github.com/0PandaDEV/Qopy/issues/3 -- [x] Поддержка macOS https://github.com/0PandaDEV/Qopy/issues/13 - -Если у вас есть идеи для функций, которые можно добавить в будущем, пожалуйста, напишите об этом [здесь](https://github.com/0pandadev/Qopy/issues). - -## 📦 Концепты - -Здесь вы можете увидеть несколько концепцов, которые могут быть не реализованы: - -![Clipboard](https://github.com/user-attachments/assets/45a44a13-6ebd-4f2d-84d2-55178e303a54) -![Settings](https://github.com/user-attachments/assets/bff5456a-f413-4e62-a43d-22c8e453aa87) - - -## ❤️ Пожертвования и Поддержка - -Qopy имеет открытый исходный код и бесплатен для использования. Я ценю пожертвования в поддержку постоянной разработки и улучшений. Ваши взносы являются добровольными и помогают мне улучшить приложение для всех. - - - -## ⌨️ Локальная разработка - -Вы можете использовать GitHub Codespaces для онлайн-разработки: - -[![][codespaces-shield]][codespaces-link] - -Или, чтобы настроить Qopy на вашем компьютере, вам необходимо установить Rust и bun. Затем выполните следующие действия: - -```zsh -git clone https://github.com/0pandadev/Qopy.git -cd Qopy -bun i -bun dev -``` - -> \[!Tip] -> -> Если вы заинтересованы во внесении кода, не стесняйтесь смотреть здесь [Issues](https://github.com/0pandadev/Qopy/issues). - -## 🔨 Сборка для продакшена - -Чтобы собрать для продакшена,просто выполните: - -```zsh -bun build -``` - -> \[!NOTE] -> -> Не волнуйтесь, в конце произойдет сбой, потому что он не сможет обнаружить Приватный ключ, но установочные файлы будут сгенерированы независимо от этого. -> -> Вы можете найти его в `src-tauri/target/release/bundle`. - -## 📝 Лицензия - -Qopy лицензирован под GPL-3. Смотрите [LICENSE file](./LICENCE) для дополнительной информации. - -[codespaces-link]: https://codespaces.new/0pandadev/Qopy -[codespaces-shield]: https://github.com/codespaces/badge.svg +
+ + +

Qopy

+ +Простой и исправленный менеджер буфера обмена как для Windows, так и для Linux. + + + Windows (x64) + +• + + Windows (arm64) + +
+ + Linux (deb) + +• + + Linux (rpm) + +• + + Linux (AppImage) + +
+ + macOS (Silicon) + +• + + macOS (Intel) + +
+
+Тестовые версии можно найти тут + +
+ +[discord »](https://discord.gg/invite/Y7SbYphVw9) + +> \[!IMPORTANT] +> +> **Нажав на звезду**, Вы будете получать все уведомления от Github о новых версиях без задержек \~ ⭐️ + +
+ Star History + + + + + + +
+ +[![wakatime](https://wakatime.com/badge/user/018ce503-097f-4057-9599-db20b190920c/project/fe76359d-56c2-4a13-8413-55207b6ad298.svg?style=flat_square)](https://wakatime.com/badge/user/018ce503-097f-4057-9599-db20b190920c/project/fe76359d-56c2-4a13-8413-55207b6ad298) + +## 📋 Что такое Qopy + +Qopy представляет собой исправленный менеджер буфера обмена, разработанный как простая альтернатива стандартному буферу обмена в Windows. Его цель - обеспечить более быструю и надежную работу, предоставляя при этом обширный набор функций по сравнению со своим аналогом в Windows. + +## 🚧 Дорожная карта +- [ ] [Руководство по установке](https://github.com/0PandaDEV/Qopy/blob/main/GET_STARTED.md) +- [ ] Синхронизация буфера обмена между устройствами https://github.com/0PandaDEV/Qopy/issues/8 +- [ ] Настройки https://github.com/0PandaDEV/Qopy/issues/2 +- [x] Метаданные для скопированных элементов https://github.com/0PandaDEV/Qopy/issues/5 +- [ ] Выделение кода https://github.com/0PandaDEV/Qopy/issues/7 +- [ ] Интеграция Streamshare https://github.com/0PandaDEV/Qopy/issues/4 +- [ ] Фильтр типов контента https://github.com/0PandaDEV/Qopy/issues/16 +- [ ] Превью для скопированных файлов https://github.com/0PandaDEV/Qopy/issues/15 +- [ ] Конвертация файлов в другие форматы https://github.com/0PandaDEV/Qopy/issues/17 +- [x] Опция для пользовательской привязки клавиш https://github.com/0PandaDEV/Qopy/issues/3 +- [x] Поддержка macOS https://github.com/0PandaDEV/Qopy/issues/13 + +Если у вас есть идеи для функций, которые можно добавить в будущем, пожалуйста, напишите об этом [здесь](https://github.com/0pandadev/Qopy/issues). + +## 📦 Концепты + +Здесь вы можете увидеть несколько концепцов, которые могут быть не реализованы: + +![Clipboard](https://github.com/user-attachments/assets/45a44a13-6ebd-4f2d-84d2-55178e303a54) +![Settings](https://github.com/user-attachments/assets/bff5456a-f413-4e62-a43d-22c8e453aa87) + + +## ❤️ Пожертвования и Поддержка + +Qopy имеет открытый исходный код и бесплатен для использования. Я ценю пожертвования в поддержку постоянной разработки и улучшений. Ваши взносы являются добровольными и помогают мне улучшить приложение для всех. + + + +## ⌨️ Локальная разработка + +Вы можете использовать GitHub Codespaces для онлайн-разработки: + +[![][codespaces-shield]][codespaces-link] + +Или, чтобы настроить Qopy на вашем компьютере, вам необходимо установить Rust и bun. Затем выполните следующие действия: + +```zsh +git clone https://github.com/0pandadev/Qopy.git +cd Qopy +bun i +bun dev +``` + +> \[!Tip] +> +> Если вы заинтересованы во внесении кода, не стесняйтесь смотреть здесь [Issues](https://github.com/0pandadev/Qopy/issues). + +## 🔨 Сборка для продакшена + +Чтобы собрать для продакшена,просто выполните: + +```zsh +bun build +``` + +> \[!NOTE] +> +> Не волнуйтесь, в конце произойдет сбой, потому что он не сможет обнаружить Приватный ключ, но установочные файлы будут сгенерированы независимо от этого. +> +> Вы можете найти его в `src-tauri/target/release/bundle`. + +## 📝 Лицензия + +Qopy лицензирован под GPL-3. Смотрите [LICENSE file](./LICENCE) для дополнительной информации. + +[codespaces-link]: https://codespaces.new/0pandadev/Qopy +[codespaces-shield]: https://github.com/codespaces/badge.svg diff --git a/app.vue b/app.vue index 0864989..aa00e9d 100644 --- a/app.vue +++ b/app.vue @@ -1,105 +1,109 @@ - - - - - + + + + + diff --git a/bun.lock b/bun.lock index 6b1dd03..bfbf8b6 100644 --- a/bun.lock +++ b/bun.lock @@ -6,15 +6,15 @@ "dependencies": { "@tauri-apps/api": "2.5.0", "@tauri-apps/cli": "2.5.0", - "@tauri-apps/plugin-autostart": "2.3.0", - "@tauri-apps/plugin-os": "2.2.1", - "@waradu/keyboard": "4.2.0", - "nuxt": "3.17.4", - "overlayscrollbars": "2.11.3", + "@tauri-apps/plugin-autostart": "2.4.0", + "@tauri-apps/plugin-os": "2.2.2", + "@waradu/keyboard": "4.3.0", + "nuxt": "3.17.5", + "overlayscrollbars": "2.11.4", "overlayscrollbars-vue": "0.5.9", - "sass-embedded": "1.89.0", + "sass-embedded": "1.89.2", "uuid": "11.1.0", - "vue": "3.5.15", + "vue": "3.5.17", }, }, }, @@ -60,7 +60,7 @@ "@babel/helpers": ["@babel/helpers@7.27.3", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.27.3" } }, "sha512-h/eKy9agOya1IGuLaZ9tEUgz+uIRXcbtOhRtUyyMf8JFmn1iT13vnl/IGVWSkdOCG/pC57U4S1jnAabAavTMwg=="], - "@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], + "@babel/parser": ["@babel/parser@7.27.5", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg=="], "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA=="], @@ -74,7 +74,7 @@ "@babel/types": ["@babel/types@7.26.10", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ=="], - "@bufbuild/protobuf": ["@bufbuild/protobuf@2.2.3", "", {}, "sha512-tFQoXHJdkEOSwj5tRIZSPNUuXK3RaR7T1nUrPgbYX1pUbvqqaaZAsfo+NXBPsz5rZMSKVFrgK1WL8Q/MSLvprg=="], + "@bufbuild/protobuf": ["@bufbuild/protobuf@2.5.2", "", {}, "sha512-foZ7qr0IsUBjzWIq+SuBLfdQCpJ1j8cTuNNT4owngTHoN5KsJb8L9t65fzz7SCeSWzescoOil/0ldqiL041ABg=="], "@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.4.0", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA=="], @@ -200,43 +200,43 @@ "@nuxt/devtools-wizard": ["@nuxt/devtools-wizard@2.4.1", "", { "dependencies": { "consola": "^3.4.2", "diff": "^7.0.0", "execa": "^8.0.1", "magicast": "^0.3.5", "pathe": "^2.0.3", "pkg-types": "^2.1.0", "prompts": "^2.4.2", "semver": "^7.7.2" }, "bin": { "devtools-wizard": "cli.mjs" } }, "sha512-2BaryhfribzQ95UxR7vLLV17Pk1Otxg9ryqH71M1Yp0mybBFs6Z3b0v+RXfCb4BwA10s/tXBhfF13DHSSJF1+A=="], - "@nuxt/kit": ["@nuxt/kit@3.17.4", "", { "dependencies": { "c12": "^3.0.4", "consola": "^3.4.2", "defu": "^6.1.4", "destr": "^2.0.5", "errx": "^0.1.0", "exsolve": "^1.0.5", "ignore": "^7.0.4", "jiti": "^2.4.2", "klona": "^2.0.6", "knitwork": "^1.2.0", "mlly": "^1.7.4", "ohash": "^2.0.11", "pathe": "^2.0.3", "pkg-types": "^2.1.0", "scule": "^1.3.0", "semver": "^7.7.2", "std-env": "^3.9.0", "tinyglobby": "^0.2.13", "ufo": "^1.6.1", "unctx": "^2.4.1", "unimport": "^5.0.1", "untyped": "^2.0.0" } }, "sha512-l+hY8sy2XFfg3PigZj+PTu6+KIJzmbACTRimn1ew/gtCz+F38f6KTF4sMRTN5CUxiB8TRENgEonASmkAWfpO9Q=="], + "@nuxt/kit": ["@nuxt/kit@3.17.5", "", { "dependencies": { "c12": "^3.0.4", "consola": "^3.4.2", "defu": "^6.1.4", "destr": "^2.0.5", "errx": "^0.1.0", "exsolve": "^1.0.5", "ignore": "^7.0.5", "jiti": "^2.4.2", "klona": "^2.0.6", "knitwork": "^1.2.0", "mlly": "^1.7.4", "ohash": "^2.0.11", "pathe": "^2.0.3", "pkg-types": "^2.1.0", "scule": "^1.3.0", "semver": "^7.7.2", "std-env": "^3.9.0", "tinyglobby": "^0.2.14", "ufo": "^1.6.1", "unctx": "^2.4.1", "unimport": "^5.0.1", "untyped": "^2.0.0" } }, "sha512-NdCepmA+S/SzgcaL3oYUeSlXGYO6BXGr9K/m1D0t0O9rApF8CSq/QQ+ja5KYaYMO1kZAEWH4s2XVcE3uPrrAVg=="], - "@nuxt/schema": ["@nuxt/schema@3.17.4", "", { "dependencies": { "@vue/shared": "^3.5.14", "consola": "^3.4.2", "defu": "^6.1.4", "pathe": "^2.0.3", "std-env": "^3.9.0" } }, "sha512-bsfJdWjKNYLkVQt7Ykr9YsAql1u8Tuo6iecSUOltTIhsvAIYsknRFPHoNKNmaiv/L6FgCQgUgQppPTPUAXiJQQ=="], + "@nuxt/schema": ["@nuxt/schema@3.17.5", "", { "dependencies": { "@vue/shared": "^3.5.16", "consola": "^3.4.2", "defu": "^6.1.4", "pathe": "^2.0.3", "std-env": "^3.9.0" } }, "sha512-A1DSQk2uXqRHXlgLWDeFCyZk/yPo9oMBMb9OsbVko9NLv9du2DO2cs9RQ68Amvdk8O2nG7/FxAMNnkMdQ8OexA=="], "@nuxt/telemetry": ["@nuxt/telemetry@2.6.6", "", { "dependencies": { "@nuxt/kit": "^3.15.4", "citty": "^0.1.6", "consola": "^3.4.2", "destr": "^2.0.3", "dotenv": "^16.4.7", "git-url-parse": "^16.0.1", "is-docker": "^3.0.0", "ofetch": "^1.4.1", "package-manager-detector": "^1.1.0", "pathe": "^2.0.3", "rc9": "^2.1.2", "std-env": "^3.8.1" }, "bin": { "nuxt-telemetry": "bin/nuxt-telemetry.mjs" } }, "sha512-Zh4HJLjzvm3Cq9w6sfzIFyH9ozK5ePYVfCUzzUQNiZojFsI2k1QkSBrVI9BGc6ArKXj/O6rkI6w7qQ+ouL8Cag=="], - "@nuxt/vite-builder": ["@nuxt/vite-builder@3.17.4", "", { "dependencies": { "@nuxt/kit": "3.17.4", "@rollup/plugin-replace": "^6.0.2", "@vitejs/plugin-vue": "^5.2.4", "@vitejs/plugin-vue-jsx": "^4.2.0", "autoprefixer": "^10.4.21", "consola": "^3.4.2", "cssnano": "^7.0.7", "defu": "^6.1.4", "esbuild": "^0.25.4", "escape-string-regexp": "^5.0.0", "exsolve": "^1.0.5", "externality": "^1.0.2", "get-port-please": "^3.1.2", "h3": "^1.15.3", "jiti": "^2.4.2", "knitwork": "^1.2.0", "magic-string": "^0.30.17", "mlly": "^1.7.4", "mocked-exports": "^0.1.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^1.0.0", "pkg-types": "^2.1.0", "postcss": "^8.5.3", "rollup-plugin-visualizer": "^5.14.0", "std-env": "^3.9.0", "ufo": "^1.6.1", "unenv": "^2.0.0-rc.17", "unplugin": "^2.3.4", "vite": "^6.3.5", "vite-node": "^3.1.4", "vite-plugin-checker": "^0.9.3", "vue-bundle-renderer": "^2.1.1" }, "peerDependencies": { "vue": "^3.3.4" } }, "sha512-MRcGe02nEDpu+MnRJcmgVfHdzgt9tWvxVdJbhfd6oyX19plw/CANjgHedlpUNUxqeWXC6CQfGvoVJXn3bQlEqA=="], + "@nuxt/vite-builder": ["@nuxt/vite-builder@3.17.5", "", { "dependencies": { "@nuxt/kit": "3.17.5", "@rollup/plugin-replace": "^6.0.2", "@vitejs/plugin-vue": "^5.2.4", "@vitejs/plugin-vue-jsx": "^4.2.0", "autoprefixer": "^10.4.21", "consola": "^3.4.2", "cssnano": "^7.0.7", "defu": "^6.1.4", "esbuild": "^0.25.5", "escape-string-regexp": "^5.0.0", "exsolve": "^1.0.5", "externality": "^1.0.2", "get-port-please": "^3.1.2", "h3": "^1.15.3", "jiti": "^2.4.2", "knitwork": "^1.2.0", "magic-string": "^0.30.17", "mlly": "^1.7.4", "mocked-exports": "^0.1.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^1.0.0", "pkg-types": "^2.1.0", "postcss": "^8.5.4", "rollup-plugin-visualizer": "^6.0.1", "std-env": "^3.9.0", "ufo": "^1.6.1", "unenv": "^2.0.0-rc.17", "unplugin": "^2.3.5", "vite": "^6.3.5", "vite-node": "^3.2.0", "vite-plugin-checker": "^0.9.3", "vue-bundle-renderer": "^2.1.1" }, "peerDependencies": { "vue": "^3.3.4" } }, "sha512-SKlm73FuuPj1ZdVJ1JQfUed/lO5l7iJMbM+9K+CMXnifu7vV2ITaSxu8uZ/ice1FeLYwOZKEsjnJXB0QpqDArQ=="], - "@oxc-parser/binding-darwin-arm64": ["@oxc-parser/binding-darwin-arm64@0.71.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-7R7TuHWL2hZ8BbRdxXlVJTE0os7TM6LL2EX2OkIz41B3421JeIU+2YH+IV55spIUy5E5ynesLk0IdpSSPVZ25Q=="], + "@oxc-parser/binding-darwin-arm64": ["@oxc-parser/binding-darwin-arm64@0.72.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-g6wgcfL7At4wHNHutl0NmPZTAju+cUSmSX5WGUMyTJmozRzhx8E9a2KL4rTqNJPwEpbCFrgC29qX9f4fpDnUpA=="], - "@oxc-parser/binding-darwin-x64": ["@oxc-parser/binding-darwin-x64@0.71.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Q7QshRy7cDvpvWAH+qy2U8O9PKo5yEKFqPruD2OSOM8igy/GLIC21dAd6iCcqXRZxaqzN9c4DaXFtEZfq4NWsw=="], + "@oxc-parser/binding-darwin-x64": ["@oxc-parser/binding-darwin-x64@0.72.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-pc+tplB2fd0AqdnXY90FguqSF2OwbxXwrMOLAMmsUiK4/ytr8Z/ftd49+d27GgvQJKeg2LfnIbskaQtY/j2tAA=="], - "@oxc-parser/binding-freebsd-x64": ["@oxc-parser/binding-freebsd-x64@0.71.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-z8NNBBseLriz2p+eJ8HWC+A8P+MsO8HCtXie9zaVlVcXSiUuBroRWeXopvHN4r+tLzmN2iLXlXprJdNhXNgobQ=="], + "@oxc-parser/binding-freebsd-x64": ["@oxc-parser/binding-freebsd-x64@0.72.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-igBR6rOvL8t5SBm1f1rjtWNsjB53HNrM3au582JpYzWxOqCjeA5Jlm9KZbjQJC+J8SPB9xyljM7G+6yGZ2UAkQ=="], - "@oxc-parser/binding-linux-arm-gnueabihf": ["@oxc-parser/binding-linux-arm-gnueabihf@0.71.0", "", { "os": "linux", "cpu": "arm" }, "sha512-QZQcWMduFRWddqvjgLvsWoeellFjvWqvdI0O1m5hoMEykv2/Ag8d7IZbBwRwFqKBuK4UzpBNt4jZaYzRsv1irg=="], + "@oxc-parser/binding-linux-arm-gnueabihf": ["@oxc-parser/binding-linux-arm-gnueabihf@0.72.3", "", { "os": "linux", "cpu": "arm" }, "sha512-/izdr3wg7bK+2RmNhZXC2fQwxbaTH3ELeqdR+Wg4FiEJ/C7ZBIjfB0E734bZGgbDu+rbEJTBlbG77XzY0wRX/Q=="], - "@oxc-parser/binding-linux-arm-musleabihf": ["@oxc-parser/binding-linux-arm-musleabihf@0.71.0", "", { "os": "linux", "cpu": "arm" }, "sha512-lTDc2WCzllVFXugUHQGR904CksA5BiHc35mcH6nJm6h0FCdoyn9zefW8Pelku5ET39JgO1OENEm/AyNvf/FzIw=="], + "@oxc-parser/binding-linux-arm-musleabihf": ["@oxc-parser/binding-linux-arm-musleabihf@0.72.3", "", { "os": "linux", "cpu": "arm" }, "sha512-Vz7C+qJb22HIFl3zXMlwvlTOR+MaIp5ps78060zsdeZh2PUGlYuUYkYXtGEjJV3kc8aKFj79XKqAY1EPG2NWQA=="], - "@oxc-parser/binding-linux-arm64-gnu": ["@oxc-parser/binding-linux-arm64-gnu@0.71.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-mAA6JGS+MB+gbN5y/KuQ095EHYGF7a/FaznM7klk5CaCap/UdiRWCVinVV6xXmejOPZMnrkr6R5Kqi6dHRsm2g=="], + "@oxc-parser/binding-linux-arm64-gnu": ["@oxc-parser/binding-linux-arm64-gnu@0.72.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-nomoMe2VpVxW767jhF+G3mDGmE0U6nvvi5nw9Edqd/5DIylQfq/lEGUWL7qITk+E72YXBsnwHtpRRlIAJOMyZg=="], - "@oxc-parser/binding-linux-arm64-musl": ["@oxc-parser/binding-linux-arm64-musl@0.71.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-PaPmIEM0yldXSrO1Icrx6/DwnMXpEOv0bDVa0LFtwy2I+aiTiX7OVRB3pJCg8FEV9P+L48s9XW0Oaz+Dz3o3sQ=="], + "@oxc-parser/binding-linux-arm64-musl": ["@oxc-parser/binding-linux-arm64-musl@0.72.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-4DswiIK5dI7hFqcMKWtZ7IZnWkRuskh6poI1ad4gkY2p678NOGtl6uOGCCRlDmLOOhp3R27u4VCTzQ6zra977w=="], - "@oxc-parser/binding-linux-riscv64-gnu": ["@oxc-parser/binding-linux-riscv64-gnu@0.71.0", "", { "os": "linux", "cpu": "none" }, "sha512-+AEGO6gOSSEqWTrCCYayNMMPe/qi83o1czQ5bytEFQtyvWdgLwliqqShpJtgSLj1SNWi94HiA/VOfqqZnGE1AQ=="], + "@oxc-parser/binding-linux-riscv64-gnu": ["@oxc-parser/binding-linux-riscv64-gnu@0.72.3", "", { "os": "linux", "cpu": "none" }, "sha512-R9GEiA4WFPGU/3RxAhEd6SaMdpqongGTvGEyTvYCS/MAQyXKxX/LFvc2xwjdvESpjIemmc/12aTTq6if28vHkQ=="], - "@oxc-parser/binding-linux-s390x-gnu": ["@oxc-parser/binding-linux-s390x-gnu@0.71.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-zqFnheBACFzrRl401ylXufNl1YsOdVa8jwS2iSCwJFx4/JdQhE6Y4YWoEjQ/pzeRZXwI5FX4C607rQe2YdhggQ=="], + "@oxc-parser/binding-linux-s390x-gnu": ["@oxc-parser/binding-linux-s390x-gnu@0.72.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-/sEYJQMVqikZO8gK9VDPT4zXo9du3gvvu8jp6erMmW5ev+14PErWRypJjktp0qoTj+uq4MzXro0tg7U+t5hP1w=="], - "@oxc-parser/binding-linux-x64-gnu": ["@oxc-parser/binding-linux-x64-gnu@0.71.0", "", { "os": "linux", "cpu": "x64" }, "sha512-steSQTwv3W+/hpES4/9E3vNohou1FXJLNWLDbYHDaBI9gZdYJp6zwALC8EShCz0NoQvCu4THD3IBsTBHvFBNyw=="], + "@oxc-parser/binding-linux-x64-gnu": ["@oxc-parser/binding-linux-x64-gnu@0.72.3", "", { "os": "linux", "cpu": "x64" }, "sha512-hlyljEZ0sMPKJQCd5pxnRh2sAf/w+Ot2iJecgV9Hl3brrYrYCK2kofC0DFaJM3NRmG/8ZB3PlxnSRSKZTocwCw=="], - "@oxc-parser/binding-linux-x64-musl": ["@oxc-parser/binding-linux-x64-musl@0.71.0", "", { "os": "linux", "cpu": "x64" }, "sha512-mV8j/haQBZRU2QnwZe0UIpnhpPBL9dFk1tgNVSH9tV7cV4xUZPn7pFDqMriAmpD7GLfmxbZMInDkujokd63M7Q=="], + "@oxc-parser/binding-linux-x64-musl": ["@oxc-parser/binding-linux-x64-musl@0.72.3", "", { "os": "linux", "cpu": "x64" }, "sha512-T17S8ORqAIq+YDFMvLfbNdAiYHYDM1+sLMNhesR5eWBtyTHX510/NbgEvcNemO9N6BNR7m4A9o+q468UG+dmbg=="], - "@oxc-parser/binding-wasm32-wasi": ["@oxc-parser/binding-wasm32-wasi@0.71.0", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.10" }, "cpu": "none" }, "sha512-P8ScINpuihkkBX8BrN/4x4ka2+izncHh7/hHxxuPZDZTVMyNNnL1uSoI80tN9yN7NUtUKoi9aQUaF4h22RQcIA=="], + "@oxc-parser/binding-wasm32-wasi": ["@oxc-parser/binding-wasm32-wasi@0.72.3", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.10" }, "cpu": "none" }, "sha512-x0Ojn/jyRUk6MllvVB/puSvI2tczZBIYweKVYHNv1nBatjPRiqo+6/uXiKrZwSfGLkGARrKkTuHSa5RdZBMOdA=="], - "@oxc-parser/binding-win32-arm64-msvc": ["@oxc-parser/binding-win32-arm64-msvc@0.71.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-4jrJSdBXHmLYaghi1jvbuJmWu117wxqCpzHHgpEV9xFiRSngtClqZkNqyvcD4907e/VriEwluZ3PO3Mlp0y9cw=="], + "@oxc-parser/binding-win32-arm64-msvc": ["@oxc-parser/binding-win32-arm64-msvc@0.72.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-kRVAl87ugRjLZTm9vGUyiXU50mqxLPHY81rgnZUP1HtNcqcmTQtM/wUKQL2UdqvhA6xm6zciqzqCgJfU+RW8uA=="], - "@oxc-parser/binding-win32-x64-msvc": ["@oxc-parser/binding-win32-x64-msvc@0.71.0", "", { "os": "win32", "cpu": "x64" }, "sha512-zF7xF19DOoANym/xwVClYH1tiW3S70W8ZDrMHdrEB7gZiTYLCIKIRMrpLVKaRia6LwEo7X0eduwdBa5QFawxOw=="], + "@oxc-parser/binding-win32-x64-msvc": ["@oxc-parser/binding-win32-x64-msvc@0.72.3", "", { "os": "win32", "cpu": "x64" }, "sha512-vpVdoGAP5iGE5tIEPJgr7FkQJZA+sKjMkg5x1jarWJ1nnBamfGsfYiZum4QjCfW7jb+pl42rHVSS3lRmMPcyrQ=="], - "@oxc-project/types": ["@oxc-project/types@0.71.0", "", {}, "sha512-5CwQ4MI+P4MQbjLWXgNurA+igGwu/opNetIE13LBs9+V93R64MLvDKOOLZIXSzEfovU3Zef3q3GjPnMTgJTn2w=="], + "@oxc-project/types": ["@oxc-project/types@0.72.3", "", {}, "sha512-CfAC4wrmMkUoISpQkFAIfMVvlPfQV3xg7ZlcqPXPOIMQhdKIId44G8W0mCPgtpWdFFAyJ+SFtiM+9vbyCkoVng=="], "@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="], @@ -368,9 +368,9 @@ "@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.5.0", "", { "os": "win32", "cpu": "x64" }, "sha512-lj43EFYbnAta8pd9JnUq87o+xRUR0odz+4rixBtTUwUgdRdwQ2V9CzFtsMu6FQKpFQ6mujRK6P1IEwhL6ADRsQ=="], - "@tauri-apps/plugin-autostart": ["@tauri-apps/plugin-autostart@2.3.0", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-yxQTpc4NolT1r317yjKVhrG+YwCWPBOj7p+70m/q0w1JHc53pGcHmTboAbA3kGY6PQ+9y9oE7cdmHq7PH9z/SQ=="], + "@tauri-apps/plugin-autostart": ["@tauri-apps/plugin-autostart@2.4.0", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-Ul5+M92A8hoZRXuUGp5FdXe5fCN07+8AmiY4W+e1688iMuny3hK9KEycPR+ByodhgI3ZCQtdVMLvjGwlkwm9cQ=="], - "@tauri-apps/plugin-os": ["@tauri-apps/plugin-os@2.2.1", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-cNYpNri2CCc6BaNeB6G/mOtLvg8dFyFQyCUdf2y0K8PIAKGEWdEcu8DECkydU2B+oj4OJihDPD2de5K6cbVl9A=="], + "@tauri-apps/plugin-os": ["@tauri-apps/plugin-os@2.2.2", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-pZ03bQeRTgid5u5F5nVLhJ6+nS4caAZggwaeZMsChuFvV2SV+EEJkf4XhH1L5fsRnEKlNoyHO5oA5viAy7RtNw=="], "@trysound/sax": ["@trysound/sax@0.2.0", "", {}, "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA=="], @@ -412,13 +412,13 @@ "@vue/babel-plugin-resolve-type": ["@vue/babel-plugin-resolve-type@1.4.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/helper-module-imports": "^7.25.9", "@babel/helper-plugin-utils": "^7.26.5", "@babel/parser": "^7.26.9", "@vue/compiler-sfc": "^3.5.13" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-4xqDRRbQQEWHQyjlYSgZsWj44KfiF6D+ktCuXyZ8EnVDYV3pztmXJDf1HveAjUAXxAnR8daCQT51RneWWxtTyQ=="], - "@vue/compiler-core": ["@vue/compiler-core@3.5.15", "", { "dependencies": { "@babel/parser": "^7.27.2", "@vue/shared": "3.5.15", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-nGRc6YJg/kxNqbv/7Tg4juirPnjHvuVdhcmDvQWVZXlLHjouq7VsKmV1hIxM/8yKM0VUfwT/Uzc0lO510ltZqw=="], + "@vue/compiler-core": ["@vue/compiler-core@3.5.17", "", { "dependencies": { "@babel/parser": "^7.27.5", "@vue/shared": "3.5.17", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA=="], - "@vue/compiler-dom": ["@vue/compiler-dom@3.5.15", "", { "dependencies": { "@vue/compiler-core": "3.5.15", "@vue/shared": "3.5.15" } }, "sha512-ZelQd9n+O/UCBdL00rlwCrsArSak+YLZpBVuNDio1hN3+wrCshYZEDUO3khSLAzPbF1oQS2duEoMDUHScUlYjA=="], + "@vue/compiler-dom": ["@vue/compiler-dom@3.5.17", "", { "dependencies": { "@vue/compiler-core": "3.5.17", "@vue/shared": "3.5.17" } }, "sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ=="], - "@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.15", "", { "dependencies": { "@babel/parser": "^7.27.2", "@vue/compiler-core": "3.5.15", "@vue/compiler-dom": "3.5.15", "@vue/compiler-ssr": "3.5.15", "@vue/shared": "3.5.15", "estree-walker": "^2.0.2", "magic-string": "^0.30.17", "postcss": "^8.5.3", "source-map-js": "^1.2.1" } }, "sha512-3zndKbxMsOU6afQWer75Zot/aydjtxNj0T2KLg033rAFaQUn2PGuE32ZRe4iMhflbTcAxL0yEYsRWFxtPro8RQ=="], + "@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.17", "", { "dependencies": { "@babel/parser": "^7.27.5", "@vue/compiler-core": "3.5.17", "@vue/compiler-dom": "3.5.17", "@vue/compiler-ssr": "3.5.17", "@vue/shared": "3.5.17", "estree-walker": "^2.0.2", "magic-string": "^0.30.17", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww=="], - "@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.15", "", { "dependencies": { "@vue/compiler-dom": "3.5.15", "@vue/shared": "3.5.15" } }, "sha512-gShn8zRREZbrXqTtmLSCffgZXDWv8nHc/GhsW+mbwBfNZL5pI96e7IWcIq8XGQe1TLtVbu7EV9gFIVSmfyarPg=="], + "@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.17", "", { "dependencies": { "@vue/compiler-dom": "3.5.17", "@vue/shared": "3.5.17" } }, "sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ=="], "@vue/devtools-api": ["@vue/devtools-api@6.6.4", "", {}, "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="], @@ -428,17 +428,17 @@ "@vue/devtools-shared": ["@vue/devtools-shared@7.7.6", "", { "dependencies": { "rfdc": "^1.4.1" } }, "sha512-yFEgJZ/WblEsojQQceuyK6FzpFDx4kqrz2ohInxNj5/DnhoX023upTv4OD6lNPLAA5LLkbwPVb10o/7b+Y4FVA=="], - "@vue/reactivity": ["@vue/reactivity@3.5.15", "", { "dependencies": { "@vue/shared": "3.5.15" } }, "sha512-GaA5VUm30YWobCwpvcs9nvFKf27EdSLKDo2jA0IXzGS344oNpFNbEQ9z+Pp5ESDaxyS8FcH0vFN/XSe95BZtHQ=="], + "@vue/reactivity": ["@vue/reactivity@3.5.17", "", { "dependencies": { "@vue/shared": "3.5.17" } }, "sha512-l/rmw2STIscWi7SNJp708FK4Kofs97zc/5aEPQh4bOsReD/8ICuBcEmS7KGwDj5ODQLYWVN2lNibKJL1z5b+Lw=="], - "@vue/runtime-core": ["@vue/runtime-core@3.5.15", "", { "dependencies": { "@vue/reactivity": "3.5.15", "@vue/shared": "3.5.15" } }, "sha512-CZAlIOQ93nj0OPpWWOx4+QDLCMzBNY85IQR4Voe6vIID149yF8g9WQaWnw042f/6JfvLttK7dnyWlC1EVCRK8Q=="], + "@vue/runtime-core": ["@vue/runtime-core@3.5.17", "", { "dependencies": { "@vue/reactivity": "3.5.17", "@vue/shared": "3.5.17" } }, "sha512-QQLXa20dHg1R0ri4bjKeGFKEkJA7MMBxrKo2G+gJikmumRS7PTD4BOU9FKrDQWMKowz7frJJGqBffYMgQYS96Q=="], - "@vue/runtime-dom": ["@vue/runtime-dom@3.5.15", "", { "dependencies": { "@vue/reactivity": "3.5.15", "@vue/runtime-core": "3.5.15", "@vue/shared": "3.5.15", "csstype": "^3.1.3" } }, "sha512-wFplHKzKO/v998up2iCW3RN9TNUeDMhdBcNYZgs5LOokHntrB48dyuZHspcahKZczKKh3v6i164gapMPxBTKNw=="], + "@vue/runtime-dom": ["@vue/runtime-dom@3.5.17", "", { "dependencies": { "@vue/reactivity": "3.5.17", "@vue/runtime-core": "3.5.17", "@vue/shared": "3.5.17", "csstype": "^3.1.3" } }, "sha512-8El0M60TcwZ1QMz4/os2MdlQECgGoVHPuLnQBU3m9h3gdNRW9xRmI8iLS4t/22OQlOE6aJvNNlBiCzPHur4H9g=="], - "@vue/server-renderer": ["@vue/server-renderer@3.5.15", "", { "dependencies": { "@vue/compiler-ssr": "3.5.15", "@vue/shared": "3.5.15" }, "peerDependencies": { "vue": "3.5.15" } }, "sha512-Gehc693kVTYkLt6QSYEjGvqvdK2zZ/gf/D5zkgmvBdeB30dNnVZS8yY7+IlBmHRd1rR/zwaqeu06Ij04ZxBscg=="], + "@vue/server-renderer": ["@vue/server-renderer@3.5.17", "", { "dependencies": { "@vue/compiler-ssr": "3.5.17", "@vue/shared": "3.5.17" }, "peerDependencies": { "vue": "3.5.17" } }, "sha512-BOHhm8HalujY6lmC3DbqF6uXN/K00uWiEeF22LfEsm9Q93XeJ/plHTepGwf6tqFcF7GA5oGSSAAUock3VvzaCA=="], - "@vue/shared": ["@vue/shared@3.5.15", "", {}, "sha512-bKvgFJJL1ZX9KxMCTQY6xD9Dhe3nusd1OhyOb1cJYGqvAr0Vg8FIjHPMOEVbJ9GDT9HG+Bjdn4oS8ohKP8EvoA=="], + "@vue/shared": ["@vue/shared@3.5.17", "", {}, "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg=="], - "@waradu/keyboard": ["@waradu/keyboard@4.2.0", "", { "dependencies": { "@types/node": "^22.15.3" }, "peerDependencies": { "typescript": "^5" } }, "sha512-xKb/LTVYOm9bUZUpucH772VEvkOEAKPxnx0DhtIHfiYHqpzJefZqNVzSnlj4tdjcXH+oWWLvQ2K7WB10ufzmBA=="], + "@waradu/keyboard": ["@waradu/keyboard@4.3.0", "", { "dependencies": { "@types/node": "^22.15.3" }, "peerDependencies": { "typescript": "^5" } }, "sha512-+x6sYlAjRwdXc8OUOALLs+0OY1ovJO6V0us/yae+i/IOhWAUMduqPfF9wpPvR6KkJuvORFo+eVAK1luY1LoaeA=="], "@whatwg-node/disposablestack": ["@whatwg-node/disposablestack@0.0.6", "", { "dependencies": { "@whatwg-node/promise-helpers": "^1.0.0", "tslib": "^2.6.3" } }, "sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw=="], @@ -558,7 +558,7 @@ "colorspace": ["colorspace@1.1.4", "", { "dependencies": { "color": "^3.1.3", "text-hex": "1.0.x" } }, "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w=="], - "commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], + "commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], "common-path-prefix": ["common-path-prefix@3.0.0", "", {}, "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w=="], @@ -852,7 +852,7 @@ "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], - "ignore": ["ignore@7.0.4", "", {}, "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A=="], + "ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], "image-meta": ["image-meta@0.2.1", "", {}, "sha512-K6acvFaelNxx8wc2VjbIzXKDVB0Khs0QT35U6NkGfTdCmjLNcO2945m7RFNR9/RPVFm48hq7QPzK8uGH18HCGw=="], @@ -1066,7 +1066,7 @@ "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], - "nuxt": ["nuxt@3.17.4", "", { "dependencies": { "@nuxt/cli": "^3.25.1", "@nuxt/devalue": "^2.0.2", "@nuxt/devtools": "^2.4.1", "@nuxt/kit": "3.17.4", "@nuxt/schema": "3.17.4", "@nuxt/telemetry": "^2.6.6", "@nuxt/vite-builder": "3.17.4", "@unhead/vue": "^2.0.9", "@vue/shared": "^3.5.14", "c12": "^3.0.4", "chokidar": "^4.0.3", "compatx": "^0.2.0", "consola": "^3.4.2", "cookie-es": "^2.0.0", "defu": "^6.1.4", "destr": "^2.0.5", "devalue": "^5.1.1", "errx": "^0.1.0", "esbuild": "^0.25.4", "escape-string-regexp": "^5.0.0", "estree-walker": "^3.0.3", "exsolve": "^1.0.5", "globby": "^14.1.0", "h3": "^1.15.3", "hookable": "^5.5.3", "ignore": "^7.0.4", "impound": "^1.0.0", "jiti": "^2.4.2", "klona": "^2.0.6", "knitwork": "^1.2.0", "magic-string": "^0.30.17", "mlly": "^1.7.4", "mocked-exports": "^0.1.1", "nanotar": "^0.2.0", "nitropack": "^2.11.12", "nypm": "^0.6.0", "ofetch": "^1.4.1", "ohash": "^2.0.11", "on-change": "^5.0.1", "oxc-parser": "^0.71.0", "pathe": "^2.0.3", "perfect-debounce": "^1.0.0", "pkg-types": "^2.1.0", "radix3": "^1.1.2", "scule": "^1.3.0", "semver": "^7.7.2", "std-env": "^3.9.0", "strip-literal": "^3.0.0", "tinyglobby": "0.2.13", "ufo": "^1.6.1", "ultrahtml": "^1.6.0", "uncrypto": "^0.1.3", "unctx": "^2.4.1", "unimport": "^5.0.1", "unplugin": "^2.3.4", "unplugin-vue-router": "^0.12.0", "unstorage": "^1.16.0", "untyped": "^2.0.0", "vue": "^3.5.14", "vue-bundle-renderer": "^2.1.1", "vue-devtools-stub": "^0.1.0", "vue-router": "^4.5.1" }, "peerDependencies": { "@parcel/watcher": "^2.1.0", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "optionalPeers": ["@parcel/watcher", "@types/node"], "bin": { "nuxi": "bin/nuxt.mjs", "nuxt": "bin/nuxt.mjs" } }, "sha512-49tkp7/+QVhuEOFoTDVvNV6Pc5+aI7wWjZHXzLUrt3tlWLPFh0yYbNXOc3kaxir1FuhRQHHyHZ7azCPmGukfFg=="], + "nuxt": ["nuxt@3.17.5", "", { "dependencies": { "@nuxt/cli": "^3.25.1", "@nuxt/devalue": "^2.0.2", "@nuxt/devtools": "^2.4.1", "@nuxt/kit": "3.17.5", "@nuxt/schema": "3.17.5", "@nuxt/telemetry": "^2.6.6", "@nuxt/vite-builder": "3.17.5", "@unhead/vue": "^2.0.10", "@vue/shared": "^3.5.16", "c12": "^3.0.4", "chokidar": "^4.0.3", "compatx": "^0.2.0", "consola": "^3.4.2", "cookie-es": "^2.0.0", "defu": "^6.1.4", "destr": "^2.0.5", "devalue": "^5.1.1", "errx": "^0.1.0", "esbuild": "^0.25.5", "escape-string-regexp": "^5.0.0", "estree-walker": "^3.0.3", "exsolve": "^1.0.5", "h3": "^1.15.3", "hookable": "^5.5.3", "ignore": "^7.0.5", "impound": "^1.0.0", "jiti": "^2.4.2", "klona": "^2.0.6", "knitwork": "^1.2.0", "magic-string": "^0.30.17", "mlly": "^1.7.4", "mocked-exports": "^0.1.1", "nanotar": "^0.2.0", "nitropack": "^2.11.12", "nypm": "^0.6.0", "ofetch": "^1.4.1", "ohash": "^2.0.11", "on-change": "^5.0.1", "oxc-parser": "^0.72.2", "pathe": "^2.0.3", "perfect-debounce": "^1.0.0", "pkg-types": "^2.1.0", "radix3": "^1.1.2", "scule": "^1.3.0", "semver": "^7.7.2", "std-env": "^3.9.0", "strip-literal": "^3.0.0", "tinyglobby": "0.2.14", "ufo": "^1.6.1", "ultrahtml": "^1.6.0", "uncrypto": "^0.1.3", "unctx": "^2.4.1", "unimport": "^5.0.1", "unplugin": "^2.3.5", "unplugin-vue-router": "^0.12.0", "unstorage": "^1.16.0", "untyped": "^2.0.0", "vue": "^3.5.16", "vue-bundle-renderer": "^2.1.1", "vue-devtools-stub": "^0.1.0", "vue-router": "^4.5.1" }, "peerDependencies": { "@parcel/watcher": "^2.1.0", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "optionalPeers": ["@parcel/watcher", "@types/node"], "bin": { "nuxi": "bin/nuxt.mjs", "nuxt": "bin/nuxt.mjs" } }, "sha512-HWTWpM1/RDcCt9DlnzrPcNvUmGqc62IhlZJvr7COSfnJq2lKYiBKIIesEaOF+57Qjw7TfLPc1DQVBNtxfKBxEw=="], "nypm": ["nypm@0.6.0", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "pathe": "^2.0.3", "pkg-types": "^2.0.0", "tinyexec": "^0.3.2" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-mn8wBFV9G9+UFHIrq+pZ2r2zL4aPau/by3kJb3cM7+5tQHMt6HGQB8FDIeKFYp8o0D2pnH6nVsO88N4AmUxIWg=="], @@ -1088,11 +1088,11 @@ "open": ["open@10.1.2", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "is-wsl": "^3.1.0" } }, "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw=="], - "overlayscrollbars": ["overlayscrollbars@2.11.3", "", {}, "sha512-8frVuHyBEOoWlO8VPlp7N+5XI1IrMkzWFR4GjPaTlvjdHQ+XN1C+hMQJpIy0QK1jMAK/cSLVRPG0jirqX0gA0A=="], + "overlayscrollbars": ["overlayscrollbars@2.11.4", "", {}, "sha512-GKYQo3OZ1QWnppNjQVv5hfpn+glYUxc6+ufW+ivdXUyLWFNc01XoH2Z36KGM4I8e5pXYeA3ElNItcXiLvmUhnQ=="], "overlayscrollbars-vue": ["overlayscrollbars-vue@0.5.9", "", { "peerDependencies": { "overlayscrollbars": "^2.0.0", "vue": "^3.2.25" } }, "sha512-zZEcsb6llnKaRwXTP44E4RrmwuH+eAi70mgCdiiPwcPBE2H99Vs2V0q7sWnEanqU3462ch38e4SmIMnuH906DQ=="], - "oxc-parser": ["oxc-parser@0.71.0", "", { "dependencies": { "@oxc-project/types": "^0.71.0" }, "optionalDependencies": { "@oxc-parser/binding-darwin-arm64": "0.71.0", "@oxc-parser/binding-darwin-x64": "0.71.0", "@oxc-parser/binding-freebsd-x64": "0.71.0", "@oxc-parser/binding-linux-arm-gnueabihf": "0.71.0", "@oxc-parser/binding-linux-arm-musleabihf": "0.71.0", "@oxc-parser/binding-linux-arm64-gnu": "0.71.0", "@oxc-parser/binding-linux-arm64-musl": "0.71.0", "@oxc-parser/binding-linux-riscv64-gnu": "0.71.0", "@oxc-parser/binding-linux-s390x-gnu": "0.71.0", "@oxc-parser/binding-linux-x64-gnu": "0.71.0", "@oxc-parser/binding-linux-x64-musl": "0.71.0", "@oxc-parser/binding-wasm32-wasi": "0.71.0", "@oxc-parser/binding-win32-arm64-msvc": "0.71.0", "@oxc-parser/binding-win32-x64-msvc": "0.71.0" } }, "sha512-RXmu7qi+67RJ8E5UhKZJdliTI+AqD3gncsJecjujcYvjsCZV9KNIfu42fQAnAfLaYZuzOMRdUYh7LzV3F1C0Gw=="], + "oxc-parser": ["oxc-parser@0.72.3", "", { "dependencies": { "@oxc-project/types": "^0.72.3" }, "optionalDependencies": { "@oxc-parser/binding-darwin-arm64": "0.72.3", "@oxc-parser/binding-darwin-x64": "0.72.3", "@oxc-parser/binding-freebsd-x64": "0.72.3", "@oxc-parser/binding-linux-arm-gnueabihf": "0.72.3", "@oxc-parser/binding-linux-arm-musleabihf": "0.72.3", "@oxc-parser/binding-linux-arm64-gnu": "0.72.3", "@oxc-parser/binding-linux-arm64-musl": "0.72.3", "@oxc-parser/binding-linux-riscv64-gnu": "0.72.3", "@oxc-parser/binding-linux-s390x-gnu": "0.72.3", "@oxc-parser/binding-linux-x64-gnu": "0.72.3", "@oxc-parser/binding-linux-x64-musl": "0.72.3", "@oxc-parser/binding-wasm32-wasi": "0.72.3", "@oxc-parser/binding-win32-arm64-msvc": "0.72.3", "@oxc-parser/binding-win32-x64-msvc": "0.72.3" } }, "sha512-JYQeJKDcUTTZ/uTdJ+fZBGFjAjkLD1h0p3Tf44ZYXRcoMk+57d81paNPFAAwzrzzqhZmkGvKKXDxwyhJXYZlpg=="], "p-event": ["p-event@6.0.1", "", { "dependencies": { "p-timeout": "^6.1.2" } }, "sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w=="], @@ -1142,7 +1142,7 @@ "pkg-types": ["pkg-types@2.1.0", "", { "dependencies": { "confbox": "^0.2.1", "exsolve": "^1.0.1", "pathe": "^2.0.3" } }, "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A=="], - "postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], + "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], "postcss-calc": ["postcss-calc@10.1.1", "", { "dependencies": { "postcss-selector-parser": "^7.0.0", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.38" } }, "sha512-NYEsLHh8DgG/PRH2+G9BTuUdtf9ViS+vdoQ0YA5OQdGsfN4ztiwtDWNtBl9EKeqNMFnIu8IKZ0cLxEQ5r5KVMw=="], @@ -1266,7 +1266,7 @@ "rollup": ["rollup@4.41.1", "", { "dependencies": { "@types/estree": "1.0.7" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.41.1", "@rollup/rollup-android-arm64": "4.41.1", "@rollup/rollup-darwin-arm64": "4.41.1", "@rollup/rollup-darwin-x64": "4.41.1", "@rollup/rollup-freebsd-arm64": "4.41.1", "@rollup/rollup-freebsd-x64": "4.41.1", "@rollup/rollup-linux-arm-gnueabihf": "4.41.1", "@rollup/rollup-linux-arm-musleabihf": "4.41.1", "@rollup/rollup-linux-arm64-gnu": "4.41.1", "@rollup/rollup-linux-arm64-musl": "4.41.1", "@rollup/rollup-linux-loongarch64-gnu": "4.41.1", "@rollup/rollup-linux-powerpc64le-gnu": "4.41.1", "@rollup/rollup-linux-riscv64-gnu": "4.41.1", "@rollup/rollup-linux-riscv64-musl": "4.41.1", "@rollup/rollup-linux-s390x-gnu": "4.41.1", "@rollup/rollup-linux-x64-gnu": "4.41.1", "@rollup/rollup-linux-x64-musl": "4.41.1", "@rollup/rollup-win32-arm64-msvc": "4.41.1", "@rollup/rollup-win32-ia32-msvc": "4.41.1", "@rollup/rollup-win32-x64-msvc": "4.41.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw=="], - "rollup-plugin-visualizer": ["rollup-plugin-visualizer@5.14.0", "", { "dependencies": { "open": "^8.4.0", "picomatch": "^4.0.2", "source-map": "^0.7.4", "yargs": "^17.5.1" }, "peerDependencies": { "rolldown": "1.x", "rollup": "2.x || 3.x || 4.x" }, "optionalPeers": ["rolldown", "rollup"], "bin": { "rollup-plugin-visualizer": "dist/bin/cli.js" } }, "sha512-VlDXneTDaKsHIw8yzJAFWtrzguoJ/LnQ+lMpoVfYJ3jJF4Ihe5oYLAqLklIK/35lgUY+1yEzCkHyZ1j4A5w5fA=="], + "rollup-plugin-visualizer": ["rollup-plugin-visualizer@6.0.3", "", { "dependencies": { "open": "^8.0.0", "picomatch": "^4.0.2", "source-map": "^0.7.4", "yargs": "^17.5.1" }, "peerDependencies": { "rolldown": "1.x || ^1.0.0-beta", "rollup": "2.x || 3.x || 4.x" }, "optionalPeers": ["rolldown", "rollup"], "bin": { "rollup-plugin-visualizer": "dist/bin/cli.js" } }, "sha512-ZU41GwrkDcCpVoffviuM9Clwjy5fcUxlz0oMoTXTYsK+tcIFzbdacnrr2n8TXcHxbGKKXtOdjxM2HUS4HjkwIw=="], "run-applescript": ["run-applescript@7.0.0", "", {}, "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A=="], @@ -1278,47 +1278,39 @@ "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="], - "sass-embedded": ["sass-embedded@1.89.0", "", { "dependencies": { "@bufbuild/protobuf": "^2.0.0", "buffer-builder": "^0.2.0", "colorjs.io": "^0.5.0", "immutable": "^5.0.2", "rxjs": "^7.4.0", "supports-color": "^8.1.1", "sync-child-process": "^1.0.2", "varint": "^6.0.0" }, "optionalDependencies": { "sass-embedded-android-arm": "1.89.0", "sass-embedded-android-arm64": "1.89.0", "sass-embedded-android-ia32": "1.89.0", "sass-embedded-android-riscv64": "1.89.0", "sass-embedded-android-x64": "1.89.0", "sass-embedded-darwin-arm64": "1.89.0", "sass-embedded-darwin-x64": "1.89.0", "sass-embedded-linux-arm": "1.89.0", "sass-embedded-linux-arm64": "1.89.0", "sass-embedded-linux-ia32": "1.89.0", "sass-embedded-linux-musl-arm": "1.89.0", "sass-embedded-linux-musl-arm64": "1.89.0", "sass-embedded-linux-musl-ia32": "1.89.0", "sass-embedded-linux-musl-riscv64": "1.89.0", "sass-embedded-linux-musl-x64": "1.89.0", "sass-embedded-linux-riscv64": "1.89.0", "sass-embedded-linux-x64": "1.89.0", "sass-embedded-win32-arm64": "1.89.0", "sass-embedded-win32-ia32": "1.89.0", "sass-embedded-win32-x64": "1.89.0" }, "bin": { "sass": "dist/bin/sass.js" } }, "sha512-EDrK1el9zdgJFpocCGlxatDWaP18tJBWoM1hxzo2KJBvjdmBichXI6O6KlQrigvQPO3uJ8DfmFmAAx7s7CG6uw=="], + "sass-embedded": ["sass-embedded@1.89.2", "", { "dependencies": { "@bufbuild/protobuf": "^2.5.0", "buffer-builder": "^0.2.0", "colorjs.io": "^0.5.0", "immutable": "^5.0.2", "rxjs": "^7.4.0", "supports-color": "^8.1.1", "sync-child-process": "^1.0.2", "varint": "^6.0.0" }, "optionalDependencies": { "sass-embedded-android-arm": "1.89.2", "sass-embedded-android-arm64": "1.89.2", "sass-embedded-android-riscv64": "1.89.2", "sass-embedded-android-x64": "1.89.2", "sass-embedded-darwin-arm64": "1.89.2", "sass-embedded-darwin-x64": "1.89.2", "sass-embedded-linux-arm": "1.89.2", "sass-embedded-linux-arm64": "1.89.2", "sass-embedded-linux-musl-arm": "1.89.2", "sass-embedded-linux-musl-arm64": "1.89.2", "sass-embedded-linux-musl-riscv64": "1.89.2", "sass-embedded-linux-musl-x64": "1.89.2", "sass-embedded-linux-riscv64": "1.89.2", "sass-embedded-linux-x64": "1.89.2", "sass-embedded-win32-arm64": "1.89.2", "sass-embedded-win32-x64": "1.89.2" }, "bin": { "sass": "dist/bin/sass.js" } }, "sha512-Ack2K8rc57kCFcYlf3HXpZEJFNUX8xd8DILldksREmYXQkRHI879yy8q4mRDJgrojkySMZqmmmW1NxrFxMsYaA=="], - "sass-embedded-android-arm": ["sass-embedded-android-arm@1.89.0", "", { "os": "android", "cpu": "arm" }, "sha512-s6jxkEZQQrtyIGZX6Sbcu7tEixFG2VkqFgrX11flm/jZex7KaxnZtFace+wnYAgHqzzYpx0kNzJUpT+GXxm8CA=="], + "sass-embedded-android-arm": ["sass-embedded-android-arm@1.89.2", "", { "os": "android", "cpu": "arm" }, "sha512-oHAPTboBHRZlDBhyRB6dvDKh4KvFs+DZibDHXbkSI6dBZxMTT+Yb2ivocHnctVGucKTLQeT7+OM5DjWHyynL/A=="], - "sass-embedded-android-arm64": ["sass-embedded-android-arm64@1.89.0", "", { "os": "android", "cpu": "arm64" }, "sha512-pr4R3p5R+Ul9ZA5nzYbBJQFJXW6dMGzgpNBhmaToYDgDhmNX5kg0mZAUlGLHvisLdTiR6oEfDDr9QI6tnD2nqA=="], + "sass-embedded-android-arm64": ["sass-embedded-android-arm64@1.89.2", "", { "os": "android", "cpu": "arm64" }, "sha512-+pq7a7AUpItNyPu61sRlP6G2A8pSPpyazASb+8AK2pVlFayCSPAEgpwpCE9A2/Xj86xJZeMizzKUHxM2CBCUxA=="], - "sass-embedded-android-ia32": ["sass-embedded-android-ia32@1.89.0", "", { "os": "android", "cpu": "ia32" }, "sha512-GoNnNGYmp1F0ZMHqQbAurlQsjBMZKtDd5H60Ruq86uQFdnuNqQ9wHKJsJABxMnjfAn60IjefytM5PYTMcAmbfA=="], + "sass-embedded-android-riscv64": ["sass-embedded-android-riscv64@1.89.2", "", { "os": "android", "cpu": "none" }, "sha512-HfJJWp/S6XSYvlGAqNdakeEMPOdhBkj2s2lN6SHnON54rahKem+z9pUbCriUJfM65Z90lakdGuOfidY61R9TYg=="], - "sass-embedded-android-riscv64": ["sass-embedded-android-riscv64@1.89.0", "", { "os": "android", "cpu": "none" }, "sha512-di+i4KkKAWTNksaQYTqBEERv46qV/tvv14TPswEfak7vcTQ2pj2mvV4KGjLYfU2LqRkX/NTXix9KFthrzFN51Q=="], + "sass-embedded-android-x64": ["sass-embedded-android-x64@1.89.2", "", { "os": "android", "cpu": "x64" }, "sha512-BGPzq53VH5z5HN8de6jfMqJjnRe1E6sfnCWFd4pK+CAiuM7iw5Fx6BQZu3ikfI1l2GY0y6pRXzsVLdp/j4EKEA=="], - "sass-embedded-android-x64": ["sass-embedded-android-x64@1.89.0", "", { "os": "android", "cpu": "x64" }, "sha512-1cRRDAnmAS1wLaxfFf6PCHu9sKW8FNxdM7ZkanwxO9mztrCu/uvfqTmaurY9+RaKvPus7sGYFp46/TNtl/wRjg=="], + "sass-embedded-darwin-arm64": ["sass-embedded-darwin-arm64@1.89.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-UCm3RL/tzMpG7DsubARsvGUNXC5pgfQvP+RRFJo9XPIi6elopY5B6H4m9dRYDpHA+scjVthdiDwkPYr9+S/KGw=="], - "sass-embedded-darwin-arm64": ["sass-embedded-darwin-arm64@1.89.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-EUNUzI0UkbQ6dASPyf09S3x7fNT54PjyD594ZGTY14Yh4qTuacIj27ckLmreAJNNu5QxlbhyYuOtz+XN5bMMxA=="], + "sass-embedded-darwin-x64": ["sass-embedded-darwin-x64@1.89.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-D9WxtDY5VYtMApXRuhQK9VkPHB8R79NIIR6xxVlN2MIdEid/TZWi1MHNweieETXhWGrKhRKglwnHxxyKdJYMnA=="], - "sass-embedded-darwin-x64": ["sass-embedded-darwin-x64@1.89.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-23R8zSuB31Fq/MYpmQ38UR2C26BsYb66VVpJgWmWl/N+sgv/+l9ECuSPMbYNgM3vb9TP9wk9dgL6KkiCS5tAyg=="], + "sass-embedded-linux-arm": ["sass-embedded-linux-arm@1.89.2", "", { "os": "linux", "cpu": "arm" }, "sha512-leP0t5U4r95dc90o8TCWfxNXwMAsQhpWxTkdtySDpngoqtTy3miMd7EYNYd1znI0FN1CBaUvbdCMbnbPwygDlA=="], - "sass-embedded-linux-arm": ["sass-embedded-linux-arm@1.89.0", "", { "os": "linux", "cpu": "arm" }, "sha512-KAzA1XD74d8/fiJXxVnLfFwfpmD2XqUJZz+DL6ZAPNLH1sb+yCP7brktaOyClDc/MBu61JERdHaJjIZhfX0Yqw=="], + "sass-embedded-linux-arm64": ["sass-embedded-linux-arm64@1.89.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-2N4WW5LLsbtrWUJ7iTpjvhajGIbmDR18ZzYRywHdMLpfdPApuHPMDF5CYzHbS+LLx2UAx7CFKBnj5LLjY6eFgQ=="], - "sass-embedded-linux-arm64": ["sass-embedded-linux-arm64@1.89.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-g9Lp57qyx51ttKj0AN/edV43Hu1fBObvD7LpYwVfs6u3I95r0Adi90KujzNrUqXxJVmsfUwseY8kA8zvcRjhYA=="], + "sass-embedded-linux-musl-arm": ["sass-embedded-linux-musl-arm@1.89.2", "", { "os": "linux", "cpu": "arm" }, "sha512-Z6gG2FiVEEdxYHRi2sS5VIYBmp17351bWtOCUZ/thBM66+e70yiN6Eyqjz80DjL8haRUegNQgy9ZJqsLAAmr9g=="], - "sass-embedded-linux-ia32": ["sass-embedded-linux-ia32@1.89.0", "", { "os": "linux", "cpu": "ia32" }, "sha512-5fxBeXyvBr3pb+vyrx9V6yd7QDRXkAPbwmFVVhjqshBABOXelLysEFea7xokh/tM8JAAQ4O8Ls3eW3Eojb477g=="], + "sass-embedded-linux-musl-arm64": ["sass-embedded-linux-musl-arm64@1.89.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-nTyuaBX6U1A/cG7WJh0pKD1gY8hbg1m2SnzsyoFG+exQ0lBX/lwTLHq3nyhF+0atv7YYhYKbmfz+sjPP8CZ9lw=="], - "sass-embedded-linux-musl-arm": ["sass-embedded-linux-musl-arm@1.89.0", "", { "os": "linux", "cpu": "arm" }, "sha512-0Q1JeEU4/tzH7fwAwarfIh+Swn3aXG/jPhVsZpbR1c1VzkeaPngmXdmLJcVXsdb35tjk84DuYcFtJlE1HYGw4Q=="], + "sass-embedded-linux-musl-riscv64": ["sass-embedded-linux-musl-riscv64@1.89.2", "", { "os": "linux", "cpu": "none" }, "sha512-N6oul+qALO0SwGY8JW7H/Vs0oZIMrRMBM4GqX3AjM/6y8JsJRxkAwnfd0fDyK+aICMFarDqQonQNIx99gdTZqw=="], - "sass-embedded-linux-musl-arm64": ["sass-embedded-linux-musl-arm64@1.89.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-50oelrOtN64u15vJN9uJryIuT0+UPjyeoq0zdWbY8F7LM9294Wf+Idea+nqDUWDCj1MHndyPFmR1mjeuRouJhw=="], + "sass-embedded-linux-musl-x64": ["sass-embedded-linux-musl-x64@1.89.2", "", { "os": "linux", "cpu": "x64" }, "sha512-K+FmWcdj/uyP8GiG9foxOCPfb5OAZG0uSVq80DKgVSC0U44AdGjvAvVZkrgFEcZ6cCqlNC2JfYmslB5iqdL7tg=="], - "sass-embedded-linux-musl-ia32": ["sass-embedded-linux-musl-ia32@1.89.0", "", { "os": "linux", "cpu": "ia32" }, "sha512-ILWqpTd+0RdsSw977iVAJf4CLetIbcQgLQf17ycS1N4StZKVRZs1bBfZhg/f/HU/4p5HondPAwepgJepZZdnFA=="], + "sass-embedded-linux-riscv64": ["sass-embedded-linux-riscv64@1.89.2", "", { "os": "linux", "cpu": "none" }, "sha512-g9nTbnD/3yhOaskeqeBQETbtfDQWRgsjHok6bn7DdAuwBsyrR3JlSFyqKc46pn9Xxd9SQQZU8AzM4IR+sY0A0w=="], - "sass-embedded-linux-musl-riscv64": ["sass-embedded-linux-musl-riscv64@1.89.0", "", { "os": "linux", "cpu": "none" }, "sha512-n2V+Tdjj7SAuiuElJYhWiHjjB1YU0cuFvL1/m5K+ecdNStfHFWIzvBT6/vzQnBOWjI4eZECNVuQ8GwGWCufZew=="], + "sass-embedded-linux-x64": ["sass-embedded-linux-x64@1.89.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Ax7dKvzncyQzIl4r7012KCMBvJzOz4uwSNoyoM5IV6y5I1f5hEwI25+U4WfuTqdkv42taCMgpjZbh9ERr6JVMQ=="], - "sass-embedded-linux-musl-x64": ["sass-embedded-linux-musl-x64@1.89.0", "", { "os": "linux", "cpu": "x64" }, "sha512-KOHJdouBK3SLJKZLnFYzuxs3dn+6jaeO3p4p1JUYAcVfndcvh13Sg2sLGfOfpg7Og6ws2Nnqnx0CyL26jPJ7ag=="], + "sass-embedded-win32-arm64": ["sass-embedded-win32-arm64@1.89.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-j96iJni50ZUsfD6tRxDQE2QSYQ2WrfHxeiyAXf41Kw0V4w5KYR/Sf6rCZQLMTUOHnD16qTMVpQi20LQSqf4WGg=="], - "sass-embedded-linux-riscv64": ["sass-embedded-linux-riscv64@1.89.0", "", { "os": "linux", "cpu": "none" }, "sha512-0A/UWeKX6MYhVLWLkdX3NPKHO+mvIwzaf6TxGCy3vS3TODWaeDUeBhHShAr7YlOKv5xRGxf7Gx7FXCPV0mUyMA=="], - - "sass-embedded-linux-x64": ["sass-embedded-linux-x64@1.89.0", "", { "os": "linux", "cpu": "x64" }, "sha512-dRBoOFPDWctHPYK3hTk3YzyX/icVrXiw7oOjbtpaDr6JooqIWBe16FslkWyvQzdmfOFy80raKVjgoqT7DsznkQ=="], - - "sass-embedded-win32-arm64": ["sass-embedded-win32-arm64@1.89.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-RnlVZ14hC/W7ubzvhqnbGfjU5PFNoFP/y5qycgCy+Mezb0IKbWvZ2Lyzux8TbL3OIjOikkNpfXoNQrX706WLAA=="], - - "sass-embedded-win32-ia32": ["sass-embedded-win32-ia32@1.89.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-eFe9VMNG+90nuoE3eXDy+38+uEHGf7xcqalq5+0PVZfR+H9RlaEbvIUNflZV94+LOH8Jb4lrfuekhHgWDJLfSg=="], - - "sass-embedded-win32-x64": ["sass-embedded-win32-x64@1.89.0", "", { "os": "win32", "cpu": "x64" }, "sha512-AaGpr5R6MLCuSvkvDdRq49ebifwLcuGPk0/10hbYw9nh3jpy2/CylYubQpIpR4yPcuD1wFwFqufTXC3HJYGb0g=="], + "sass-embedded-win32-x64": ["sass-embedded-win32-x64@1.89.2", "", { "os": "win32", "cpu": "x64" }, "sha512-cS2j5ljdkQsb4PaORiClaVYynE9OAPZG/XjbOMxpQmjRIf7UroY4PEIH+Waf+y47PfXFX9SyxhYuw2NIKGbEng=="], "scule": ["scule@1.3.0", "", {}, "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g=="], @@ -1436,7 +1428,7 @@ "tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], - "tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="], + "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], "tmp": ["tmp@0.2.3", "", {}, "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w=="], @@ -1516,7 +1508,7 @@ "vite-hot-client": ["vite-hot-client@2.0.4", "", { "peerDependencies": { "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0" } }, "sha512-W9LOGAyGMrbGArYJN4LBCdOC5+Zwh7dHvOHC0KmGKkJhsOzaKbpo/jEjpPKVHIW0/jBWj8RZG0NUxfgA8BxgAg=="], - "vite-node": ["vite-node@3.1.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-6enNwYnpyDo4hEgytbmc6mYWHXDHYEn0D1/rw4Q+tnHUGtKTJsn8T1YkX6Q18wI5LCrS8CTYlBaiCqxOy2kvUA=="], + "vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="], "vite-plugin-checker": ["vite-plugin-checker@0.9.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "chokidar": "^4.0.3", "npm-run-path": "^6.0.0", "picocolors": "^1.1.1", "picomatch": "^4.0.2", "strip-ansi": "^7.1.0", "tiny-invariant": "^1.3.3", "tinyglobby": "^0.2.13", "vscode-uri": "^3.1.0" }, "peerDependencies": { "@biomejs/biome": ">=1.7", "eslint": ">=7", "meow": "^13.2.0", "optionator": "^0.9.4", "stylelint": ">=16", "typescript": "*", "vite": ">=2.0.0", "vls": "*", "vti": "*", "vue-tsc": "~2.2.10" }, "optionalPeers": ["@biomejs/biome", "eslint", "meow", "optionator", "stylelint", "typescript", "vls", "vti", "vue-tsc"] }, "sha512-Tf7QBjeBtG7q11zG0lvoF38/2AVUzzhMNu+Wk+mcsJ00Rk/FpJ4rmUviVJpzWkagbU13cGXvKpt7CMiqtxVTbQ=="], @@ -1526,7 +1518,7 @@ "vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="], - "vue": ["vue@3.5.15", "", { "dependencies": { "@vue/compiler-dom": "3.5.15", "@vue/compiler-sfc": "3.5.15", "@vue/runtime-dom": "3.5.15", "@vue/server-renderer": "3.5.15", "@vue/shared": "3.5.15" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-aD9zK4rB43JAMK/5BmS4LdPiEp8Fdh8P1Ve/XNuMF5YRf78fCyPE6FUbQwcaWQ5oZ1R2CD9NKE0FFOVpMR7gEQ=="], + "vue": ["vue@3.5.17", "", { "dependencies": { "@vue/compiler-dom": "3.5.17", "@vue/compiler-sfc": "3.5.17", "@vue/runtime-dom": "3.5.17", "@vue/server-renderer": "3.5.17", "@vue/shared": "3.5.17" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g=="], "vue-bundle-renderer": ["vue-bundle-renderer@2.1.1", "", { "dependencies": { "ufo": "^1.5.4" } }, "sha512-+qALLI5cQncuetYOXp4yScwYvqh8c6SMXee3B+M7oTZxOgtESP0l4j/fXdEJoZ+EdMxkGWIj+aSEyjXkOdmd7g=="], @@ -1584,12 +1576,16 @@ "@babel/code-frame/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + "@babel/core/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], + "@babel/core/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/core/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "@babel/generator/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], + "@babel/generator/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/helper-annotate-as-pure/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], @@ -1622,8 +1618,12 @@ "@babel/plugin-syntax-jsx/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.26.5", "", {}, "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg=="], + "@babel/template/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], + "@babel/template/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], + "@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], + "@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/traverse/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], @@ -1642,6 +1642,8 @@ "@netlify/functions/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="], + "@netlify/zip-it-and-ship-it/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], + "@netlify/zip-it-and-ship-it/@babel/types": ["@babel/types@7.27.1", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q=="], "@netlify/zip-it-and-ship-it/@vercel/nft": ["@vercel/nft@0.29.3", "", { "dependencies": { "@mapbox/node-pre-gyp": "^2.0.0", "@rollup/pluginutils": "^5.1.3", "acorn": "^8.6.0", "acorn-import-attributes": "^1.9.5", "async-sema": "^3.1.1", "bindings": "^1.4.0", "estree-walker": "2.0.2", "glob": "^10.4.5", "graceful-fs": "^4.2.9", "node-gyp-build": "^4.2.2", "picomatch": "^4.0.2", "resolve-from": "^5.0.0" }, "bin": { "nft": "out/cli.js" } }, "sha512-aVV0E6vJpuvImiMwU1/5QKkw2N96BRFE7mBYGS7FhXUoS6V7SarQ+8tuj33o7ofECz8JtHpmQ9JW+oVzOoB7MA=="], @@ -1652,6 +1654,16 @@ "@netlify/zip-it-and-ship-it/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="], + "@nuxt/devtools/@nuxt/kit": ["@nuxt/kit@3.17.4", "", { "dependencies": { "c12": "^3.0.4", "consola": "^3.4.2", "defu": "^6.1.4", "destr": "^2.0.5", "errx": "^0.1.0", "exsolve": "^1.0.5", "ignore": "^7.0.4", "jiti": "^2.4.2", "klona": "^2.0.6", "knitwork": "^1.2.0", "mlly": "^1.7.4", "ohash": "^2.0.11", "pathe": "^2.0.3", "pkg-types": "^2.1.0", "scule": "^1.3.0", "semver": "^7.7.2", "std-env": "^3.9.0", "tinyglobby": "^0.2.13", "ufo": "^1.6.1", "unctx": "^2.4.1", "unimport": "^5.0.1", "untyped": "^2.0.0" } }, "sha512-l+hY8sy2XFfg3PigZj+PTu6+KIJzmbACTRimn1ew/gtCz+F38f6KTF4sMRTN5CUxiB8TRENgEonASmkAWfpO9Q=="], + + "@nuxt/devtools/tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="], + + "@nuxt/devtools-kit/@nuxt/kit": ["@nuxt/kit@3.17.4", "", { "dependencies": { "c12": "^3.0.4", "consola": "^3.4.2", "defu": "^6.1.4", "destr": "^2.0.5", "errx": "^0.1.0", "exsolve": "^1.0.5", "ignore": "^7.0.4", "jiti": "^2.4.2", "klona": "^2.0.6", "knitwork": "^1.2.0", "mlly": "^1.7.4", "ohash": "^2.0.11", "pathe": "^2.0.3", "pkg-types": "^2.1.0", "scule": "^1.3.0", "semver": "^7.7.2", "std-env": "^3.9.0", "tinyglobby": "^0.2.13", "ufo": "^1.6.1", "unctx": "^2.4.1", "unimport": "^5.0.1", "untyped": "^2.0.0" } }, "sha512-l+hY8sy2XFfg3PigZj+PTu6+KIJzmbACTRimn1ew/gtCz+F38f6KTF4sMRTN5CUxiB8TRENgEonASmkAWfpO9Q=="], + + "@nuxt/devtools-kit/@nuxt/schema": ["@nuxt/schema@3.17.4", "", { "dependencies": { "@vue/shared": "^3.5.14", "consola": "^3.4.2", "defu": "^6.1.4", "pathe": "^2.0.3", "std-env": "^3.9.0" } }, "sha512-bsfJdWjKNYLkVQt7Ykr9YsAql1u8Tuo6iecSUOltTIhsvAIYsknRFPHoNKNmaiv/L6FgCQgUgQppPTPUAXiJQQ=="], + + "@nuxt/telemetry/@nuxt/kit": ["@nuxt/kit@3.17.4", "", { "dependencies": { "c12": "^3.0.4", "consola": "^3.4.2", "defu": "^6.1.4", "destr": "^2.0.5", "errx": "^0.1.0", "exsolve": "^1.0.5", "ignore": "^7.0.4", "jiti": "^2.4.2", "klona": "^2.0.6", "knitwork": "^1.2.0", "mlly": "^1.7.4", "ohash": "^2.0.11", "pathe": "^2.0.3", "pkg-types": "^2.1.0", "scule": "^1.3.0", "semver": "^7.7.2", "std-env": "^3.9.0", "tinyglobby": "^0.2.13", "ufo": "^1.6.1", "unctx": "^2.4.1", "unimport": "^5.0.1", "untyped": "^2.0.0" } }, "sha512-l+hY8sy2XFfg3PigZj+PTu6+KIJzmbACTRimn1ew/gtCz+F38f6KTF4sMRTN5CUxiB8TRENgEonASmkAWfpO9Q=="], + "@parcel/watcher-wasm/napi-wasm": ["napi-wasm@1.1.3", "", { "bundled": true }, "sha512-h/4nMGsHjZDCYmQVNODIrYACVJ+I9KItbG+0si6W/jSjdA9JbWDoU4LLeMXVcEQGHjttI2tuXqDrbGF7qkUHHg=="], "@poppinss/colors/kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], @@ -1666,8 +1678,6 @@ "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], - "@tauri-apps/plugin-os/@tauri-apps/api": ["@tauri-apps/api@2.3.0", "", {}, "sha512-33Z+0lX2wgZbx1SPFfqvzI6su63hCBkbzv+5NexeYjIx7WA9htdOKoRR7Dh3dJyltqS5/J8vQFyybiRoaL0hlA=="], - "@typescript-eslint/typescript-estree/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "@vercel/nft/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], @@ -1678,6 +1688,12 @@ "@vue-macros/common/pathe": ["pathe@2.0.2", "", {}, "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w=="], + "@vue/babel-plugin-jsx/@vue/shared": ["@vue/shared@3.5.15", "", {}, "sha512-bKvgFJJL1ZX9KxMCTQY6xD9Dhe3nusd1OhyOb1cJYGqvAr0Vg8FIjHPMOEVbJ9GDT9HG+Bjdn4oS8ohKP8EvoA=="], + + "@vue/babel-plugin-resolve-type/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], + + "@vue/babel-plugin-resolve-type/@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.15", "", { "dependencies": { "@babel/parser": "^7.27.2", "@vue/compiler-core": "3.5.15", "@vue/compiler-dom": "3.5.15", "@vue/compiler-ssr": "3.5.15", "@vue/shared": "3.5.15", "estree-walker": "^2.0.2", "magic-string": "^0.30.17", "postcss": "^8.5.3", "source-map-js": "^1.2.1" } }, "sha512-3zndKbxMsOU6afQWer75Zot/aydjtxNj0T2KLg033rAFaQUn2PGuE32ZRe4iMhflbTcAxL0yEYsRWFxtPro8RQ=="], + "@vue/compiler-core/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], "@vue/compiler-sfc/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], @@ -1712,6 +1728,8 @@ "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="], + "detective-vue2/@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.15", "", { "dependencies": { "@babel/parser": "^7.27.2", "@vue/compiler-core": "3.5.15", "@vue/compiler-dom": "3.5.15", "@vue/compiler-ssr": "3.5.15", "@vue/shared": "3.5.15", "estree-walker": "^2.0.2", "magic-string": "^0.30.17", "postcss": "^8.5.3", "source-map-js": "^1.2.1" } }, "sha512-3zndKbxMsOU6afQWer75Zot/aydjtxNj0T2KLg033rAFaQUn2PGuE32ZRe4iMhflbTcAxL0yEYsRWFxtPro8RQ=="], + "escodegen/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "externality/pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], @@ -1730,6 +1748,8 @@ "h3/cookie-es": ["cookie-es@1.2.2", "", {}, "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg=="], + "lambda-local/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], + "lazystream/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], "listhen/consola": ["consola@3.4.0", "", {}, "sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA=="], @@ -1758,6 +1778,10 @@ "netlify/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], + "nitropack/rollup-plugin-visualizer": ["rollup-plugin-visualizer@5.14.0", "", { "dependencies": { "open": "^8.4.0", "picomatch": "^4.0.2", "source-map": "^0.7.4", "yargs": "^17.5.1" }, "peerDependencies": { "rolldown": "1.x", "rollup": "2.x || 3.x || 4.x" }, "optionalPeers": ["rolldown", "rollup"], "bin": { "rollup-plugin-visualizer": "dist/bin/cli.js" } }, "sha512-VlDXneTDaKsHIw8yzJAFWtrzguoJ/LnQ+lMpoVfYJ3jJF4Ihe5oYLAqLklIK/35lgUY+1yEzCkHyZ1j4A5w5fA=="], + + "node-source-walk/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], + "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], "nypm/consola": ["consola@3.4.0", "", {}, "sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA=="], @@ -1774,7 +1798,7 @@ "pkg-types/exsolve": ["exsolve@1.0.4", "", {}, "sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw=="], - "postcss/nanoid": ["nanoid@3.3.8", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w=="], + "postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "postcss-colormin/browserslist": ["browserslist@4.24.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001716", "electron-to-chromium": "^1.5.149", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw=="], @@ -1798,6 +1822,8 @@ "precinct/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], + "precinct/postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], + "rc9/destr": ["destr@2.0.3", "", {}, "sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ=="], "read-pkg/unicorn-magic": ["unicorn-magic@0.1.0", "", {}, "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ=="], @@ -1826,12 +1852,12 @@ "svgo/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], - "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], - "unctx/unplugin": ["unplugin@2.1.2", "", { "dependencies": { "acorn": "^8.14.0", "webpack-virtual-modules": "^0.6.2" } }, "sha512-Q3LU0e4zxKfRko1wMV2HmP8lB9KWislY7hxXpxd+lGx0PRInE4vhMBVEZwpdVYHvtqzhSrzuIfErsob6bQfCzw=="], "unimport/acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], + "unimport/tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="], + "unixify/normalize-path": ["normalize-path@2.1.1", "", { "dependencies": { "remove-trailing-separator": "^1.0.1" } }, "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w=="], "unplugin/acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], @@ -1850,10 +1876,18 @@ "unwasm/unplugin": ["unplugin@1.16.1", "", { "dependencies": { "acorn": "^8.14.0", "webpack-virtual-modules": "^0.6.2" } }, "sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w=="], + "vite/postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], + + "vite/tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="], + "vite-dev-rpc/birpc": ["birpc@2.2.0", "", {}, "sha512-1/22obknhoj56PcE+pZPp6AbWDdY55M81/ofpPW3Ltlp9Eh4zoFFLswvZmNpRTb790CY5tsNfgbYeNOqIARJfQ=="], + "vite-node/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + "vite-plugin-checker/npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="], + "vite-plugin-checker/tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="], + "vite-plugin-inspect/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "vue-bundle-renderer/ufo": ["ufo@1.5.4", "", {}, "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ=="], @@ -1930,6 +1964,8 @@ "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], + "@netlify/zip-it-and-ship-it/@babel/parser/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], + "@netlify/zip-it-and-ship-it/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@netlify/zip-it-and-ship-it/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], @@ -1992,6 +2028,18 @@ "@netlify/zip-it-and-ship-it/glob/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], + "@nuxt/devtools-kit/@nuxt/kit/ignore": ["ignore@7.0.4", "", {}, "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A=="], + + "@nuxt/devtools-kit/@nuxt/kit/tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="], + + "@nuxt/devtools-kit/@nuxt/schema/@vue/shared": ["@vue/shared@3.5.15", "", {}, "sha512-bKvgFJJL1ZX9KxMCTQY6xD9Dhe3nusd1OhyOb1cJYGqvAr0Vg8FIjHPMOEVbJ9GDT9HG+Bjdn4oS8ohKP8EvoA=="], + + "@nuxt/devtools/@nuxt/kit/ignore": ["ignore@7.0.4", "", {}, "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A=="], + + "@nuxt/telemetry/@nuxt/kit/ignore": ["ignore@7.0.4", "", {}, "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A=="], + + "@nuxt/telemetry/@nuxt/kit/tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="], + "@vue-macros/common/@vue/compiler-sfc/@babel/parser": ["@babel/parser@7.26.7", "", { "dependencies": { "@babel/types": "^7.26.7" }, "bin": "./bin/babel-parser.js" }, "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w=="], "@vue-macros/common/@vue/compiler-sfc/@vue/compiler-core": ["@vue/compiler-core@3.5.13", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.13", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q=="], @@ -2008,6 +2056,20 @@ "@vue-macros/common/local-pkg/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], + "@vue/babel-plugin-resolve-type/@babel/parser/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], + + "@vue/babel-plugin-resolve-type/@vue/compiler-sfc/@vue/compiler-core": ["@vue/compiler-core@3.5.15", "", { "dependencies": { "@babel/parser": "^7.27.2", "@vue/shared": "3.5.15", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-nGRc6YJg/kxNqbv/7Tg4juirPnjHvuVdhcmDvQWVZXlLHjouq7VsKmV1hIxM/8yKM0VUfwT/Uzc0lO510ltZqw=="], + + "@vue/babel-plugin-resolve-type/@vue/compiler-sfc/@vue/compiler-dom": ["@vue/compiler-dom@3.5.15", "", { "dependencies": { "@vue/compiler-core": "3.5.15", "@vue/shared": "3.5.15" } }, "sha512-ZelQd9n+O/UCBdL00rlwCrsArSak+YLZpBVuNDio1hN3+wrCshYZEDUO3khSLAzPbF1oQS2duEoMDUHScUlYjA=="], + + "@vue/babel-plugin-resolve-type/@vue/compiler-sfc/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.15", "", { "dependencies": { "@vue/compiler-dom": "3.5.15", "@vue/shared": "3.5.15" } }, "sha512-gShn8zRREZbrXqTtmLSCffgZXDWv8nHc/GhsW+mbwBfNZL5pI96e7IWcIq8XGQe1TLtVbu7EV9gFIVSmfyarPg=="], + + "@vue/babel-plugin-resolve-type/@vue/compiler-sfc/@vue/shared": ["@vue/shared@3.5.15", "", {}, "sha512-bKvgFJJL1ZX9KxMCTQY6xD9Dhe3nusd1OhyOb1cJYGqvAr0Vg8FIjHPMOEVbJ9GDT9HG+Bjdn4oS8ohKP8EvoA=="], + + "@vue/babel-plugin-resolve-type/@vue/compiler-sfc/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + + "@vue/babel-plugin-resolve-type/@vue/compiler-sfc/postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], + "ast-kit/@babel/parser/@babel/types": ["@babel/types@7.26.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg=="], "ast-walker-scope/@babel/parser/@babel/types": ["@babel/types@7.26.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg=="], @@ -2024,6 +2086,20 @@ "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="], + "detective-vue2/@vue/compiler-sfc/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], + + "detective-vue2/@vue/compiler-sfc/@vue/compiler-core": ["@vue/compiler-core@3.5.15", "", { "dependencies": { "@babel/parser": "^7.27.2", "@vue/shared": "3.5.15", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-nGRc6YJg/kxNqbv/7Tg4juirPnjHvuVdhcmDvQWVZXlLHjouq7VsKmV1hIxM/8yKM0VUfwT/Uzc0lO510ltZqw=="], + + "detective-vue2/@vue/compiler-sfc/@vue/compiler-dom": ["@vue/compiler-dom@3.5.15", "", { "dependencies": { "@vue/compiler-core": "3.5.15", "@vue/shared": "3.5.15" } }, "sha512-ZelQd9n+O/UCBdL00rlwCrsArSak+YLZpBVuNDio1hN3+wrCshYZEDUO3khSLAzPbF1oQS2duEoMDUHScUlYjA=="], + + "detective-vue2/@vue/compiler-sfc/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.15", "", { "dependencies": { "@vue/compiler-dom": "3.5.15", "@vue/shared": "3.5.15" } }, "sha512-gShn8zRREZbrXqTtmLSCffgZXDWv8nHc/GhsW+mbwBfNZL5pI96e7IWcIq8XGQe1TLtVbu7EV9gFIVSmfyarPg=="], + + "detective-vue2/@vue/compiler-sfc/@vue/shared": ["@vue/shared@3.5.15", "", {}, "sha512-bKvgFJJL1ZX9KxMCTQY6xD9Dhe3nusd1OhyOb1cJYGqvAr0Vg8FIjHPMOEVbJ9GDT9HG+Bjdn4oS8ohKP8EvoA=="], + + "detective-vue2/@vue/compiler-sfc/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + + "detective-vue2/@vue/compiler-sfc/postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], + "lazystream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], "lazystream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], @@ -2038,6 +2114,10 @@ "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], + "nitropack/rollup-plugin-visualizer/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="], + + "node-source-walk/@babel/parser/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], + "parse-json/@babel/code-frame/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], "postcss-colormin/browserslist/electron-to-chromium": ["electron-to-chromium@1.5.158", "", {}, "sha512-9vcp2xHhkvraY6AHw2WMi+GDSLPX42qe2xjYaVoZqFRJiOcilVQFq9mZmpuHEQpzlgGDelKlV7ZiGcmMsc8WxQ=="], @@ -2064,6 +2144,8 @@ "postcss-reduce-initial/browserslist/update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], + "precinct/postcss/nanoid": ["nanoid@3.3.8", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w=="], + "rollup-plugin-visualizer/open/define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="], "rollup-plugin-visualizer/open/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], @@ -2086,6 +2168,8 @@ "vite-plugin-checker/npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], + "vite/postcss/nanoid": ["nanoid@3.3.8", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w=="], + "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], @@ -2094,16 +2178,44 @@ "@babel/helper-module-transforms/@babel/helper-module-imports/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + "@netlify/zip-it-and-ship-it/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@netlify/zip-it-and-ship-it/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "@vue-macros/common/@vue/compiler-sfc/@babel/parser/@babel/types": ["@babel/types@7.26.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg=="], "@vue-macros/common/@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.8", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w=="], "@vue-macros/common/local-pkg/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], + "@vue/babel-plugin-resolve-type/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@vue/babel-plugin-resolve-type/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + + "@vue/babel-plugin-resolve-type/@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.8", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w=="], + + "detective-vue2/@vue/compiler-sfc/@babel/parser/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], + + "detective-vue2/@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.8", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w=="], + "listhen/h3/unenv/mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="], + "nitropack/rollup-plugin-visualizer/open/define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="], + + "nitropack/rollup-plugin-visualizer/open/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], + + "nitropack/rollup-plugin-visualizer/open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], + + "node-source-walk/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "node-source-walk/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "unplugin-vue-router/local-pkg/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], "unplugin-vue-router/local-pkg/pkg-types/pathe": ["pathe@2.0.2", "", {}, "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w=="], + + "detective-vue2/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "detective-vue2/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], } } diff --git a/components/ActionsMenu.vue b/components/ActionsMenu.vue new file mode 100644 index 0000000..1769ef2 --- /dev/null +++ b/components/ActionsMenu.vue @@ -0,0 +1,798 @@ + + + + + diff --git a/components/BottomBar.vue b/components/BottomBar.vue index 2ec32ed..452ccbc 100644 --- a/components/BottomBar.vue +++ b/components/BottomBar.vue @@ -1,124 +1,152 @@ - - - - - + + + + + diff --git a/components/Icons/Bin.vue b/components/Icons/Bin.vue new file mode 100644 index 0000000..1cdc976 --- /dev/null +++ b/components/Icons/Bin.vue @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/components/Icons/Board.vue b/components/Icons/Board.vue new file mode 100644 index 0000000..72f40ad --- /dev/null +++ b/components/Icons/Board.vue @@ -0,0 +1,14 @@ + \ No newline at end of file diff --git a/components/Icons/Brush.vue b/components/Icons/Brush.vue new file mode 100644 index 0000000..4a664eb --- /dev/null +++ b/components/Icons/Brush.vue @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/components/Icons/Code.vue b/components/Icons/Code.vue index 975d5c2..54782af 100644 --- a/components/Icons/Code.vue +++ b/components/Icons/Code.vue @@ -1,16 +1,16 @@ - + diff --git a/components/Icons/Ctrl.vue b/components/Icons/Ctrl.vue deleted file mode 100644 index 60163bd..0000000 --- a/components/Icons/Ctrl.vue +++ /dev/null @@ -1,32 +0,0 @@ - diff --git a/components/Icons/Expand.vue b/components/Icons/Expand.vue new file mode 100644 index 0000000..76d6a1c --- /dev/null +++ b/components/Icons/Expand.vue @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/components/Icons/File.vue b/components/Icons/File.vue index 1f64eba..53c216a 100644 --- a/components/Icons/File.vue +++ b/components/Icons/File.vue @@ -1,16 +1,16 @@ - + diff --git a/components/Icons/Gear.vue b/components/Icons/Gear.vue new file mode 100644 index 0000000..acc9161 --- /dev/null +++ b/components/Icons/Gear.vue @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/components/Icons/Globe.vue b/components/Icons/Globe.vue new file mode 100644 index 0000000..a3a04ff --- /dev/null +++ b/components/Icons/Globe.vue @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/components/Icons/Image.vue b/components/Icons/Image.vue index ed67dbe..cfa11bc 100644 --- a/components/Icons/Image.vue +++ b/components/Icons/Image.vue @@ -1,15 +1,15 @@ - + diff --git a/components/Icons/K.vue b/components/Icons/K.vue deleted file mode 100644 index 8bdc675..0000000 --- a/components/Icons/K.vue +++ /dev/null @@ -1,29 +0,0 @@ - diff --git a/components/Icons/Link.vue b/components/Icons/Link.vue index 2036f60..292359e 100644 --- a/components/Icons/Link.vue +++ b/components/Icons/Link.vue @@ -1,15 +1,15 @@ - + diff --git a/components/Icons/Open.vue b/components/Icons/Open.vue new file mode 100644 index 0000000..79b297e --- /dev/null +++ b/components/Icons/Open.vue @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/components/Icons/Pen.vue b/components/Icons/Pen.vue new file mode 100644 index 0000000..8f28c5f --- /dev/null +++ b/components/Icons/Pen.vue @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/components/Icons/Rotate.vue b/components/Icons/Rotate.vue new file mode 100644 index 0000000..fab10b1 --- /dev/null +++ b/components/Icons/Rotate.vue @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/components/Icons/T.vue b/components/Icons/T.vue new file mode 100644 index 0000000..2ee84b9 --- /dev/null +++ b/components/Icons/T.vue @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/components/Icons/Text.vue b/components/Icons/Text.vue index 3b9eb2d..12f4a29 100644 --- a/components/Icons/Text.vue +++ b/components/Icons/Text.vue @@ -1,16 +1,16 @@ - + diff --git a/components/Icons/Zip.vue b/components/Icons/Zip.vue new file mode 100644 index 0000000..8c65c5f --- /dev/null +++ b/components/Icons/Zip.vue @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/components/Icons/Cmd.vue b/components/Keys/Cmd.vue similarity index 99% rename from components/Icons/Cmd.vue rename to components/Keys/Cmd.vue index 7b18f3e..97c45bc 100644 --- a/components/Icons/Cmd.vue +++ b/components/Keys/Cmd.vue @@ -1,39 +1,39 @@ - + diff --git a/components/Icons/Enter.vue b/components/Keys/Enter.vue similarity index 97% rename from components/Icons/Enter.vue rename to components/Keys/Enter.vue index e6e50a0..2b44d6f 100644 --- a/components/Icons/Enter.vue +++ b/components/Keys/Enter.vue @@ -1,41 +1,41 @@ - + diff --git a/components/Keys/Key.vue b/components/Keys/Key.vue new file mode 100644 index 0000000..6b8b7fe --- /dev/null +++ b/components/Keys/Key.vue @@ -0,0 +1,30 @@ + + + diff --git a/components/Keys/Shift.vue b/components/Keys/Shift.vue new file mode 100644 index 0000000..be27076 --- /dev/null +++ b/components/Keys/Shift.vue @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/components/Noise.vue b/components/Noise.vue index 9be572c..f3cd6fb 100644 --- a/components/Noise.vue +++ b/components/Noise.vue @@ -1,23 +1,23 @@ - - - + + + diff --git a/components/Result.vue b/components/Result.vue index 515f9f1..8bbf362 100644 --- a/components/Result.vue +++ b/components/Result.vue @@ -1,122 +1,122 @@ - - - - - + + + + + diff --git a/components/TopBar.vue b/components/TopBar.vue index 91924ec..be435ce 100644 --- a/components/TopBar.vue +++ b/components/TopBar.vue @@ -1,57 +1,57 @@ - - - - - + + + + + diff --git a/composables/useActions.ts b/composables/useActions.ts new file mode 100644 index 0000000..0db12ba --- /dev/null +++ b/composables/useActions.ts @@ -0,0 +1,222 @@ +import { invoke } from "@tauri-apps/api/core"; +import { HistoryItem } from "../types/types"; + +const { $history } = useNuxtApp(); +const { hideApp } = useAppControl(); + +export function useActions() { + const isProcessing = ref(false); + + const handleAction = async (action: string, item?: HistoryItem) => { + if (!item && action !== "settings" && action !== "delete-all") return; + + isProcessing.value = true; + + try { + switch (action) { + case "paste-to-app": + await pasteToCurrentApp(item); + break; + case "copy": + // await copyToClipboard(item); + break; + case "delete": + await deleteEntry(item); + break; + case "delete-all": + // await deleteAllEntries(); + break; + case "settings": + openSettings(); + break; + case "paste-plain": + // await pasteAsPlainText(item); + break; + case "edit-text": + // openTextEditor(item); + break; + case "rotate-image": + // await rotateImage(item); + break; + case "resize-image": + // openImageResizer(item); + break; + case "compress-image": + // await compressImage(item); + break; + case "open-file": + // await openFile(item); + break; + case "compress-file": + // await compressFile(item); + break; + case "open-link": + // await openInBrowser(item); + break; + case "copy-hex": + // await copyColorFormat(item, "hex"); + break; + case "copy-rgba": + // await copyColorFormat(item, "rgba"); + break; + case "copy-hsla": + // await copyColorFormat(item, "hsla"); + break; + default: + console.warn(`Action ${action} not implemented`); + } + } catch (error) { + console.error(`Error executing action ${action}:`, error); + } finally { + isProcessing.value = false; + } + }; + + const pasteToCurrentApp = async (item?: HistoryItem) => { + if (!item) return; + + let content = item.content; + let contentType: string = item.content_type; + if (contentType === "image") { + try { + content = await $history.readImage({ filename: content }); + } catch (error) { + console.error("Error reading image file:", error); + return; + } + } + await hideApp(); + await $history.writeAndPaste({ content, contentType }); + }; + + // const copyToClipboard = async (item?: HistoryItem) => { + // if (!item) return; + + // try { + // switch (item.content_type) { + // case ContentType.Text: + // case ContentType.Link: + // case ContentType.Code: + // await writeText(item.content); + // break; + // case ContentType.Image: + // await invoke("copy_image_to_clipboard", { path: item.file_path }); + // break; + // case ContentType.File: + // await invoke("copy_file_reference", { path: item.file_path }); + // break; + // case ContentType.Color: + // await writeText(item.content); + // break; + // default: + // console.warn(`Copying type ${item.content_type} not implemented`); + // } + // } catch (error) { + // console.error("Failed to copy to clipboard:", error); + // } + // }; + + const deleteEntry = async (item?: HistoryItem) => { + if (!item) return; + try { + await invoke("delete_history_item", { id: item.id }); + } catch (error) { + console.error("Failed to delete entry:", error); + } + }; + + // const deleteAllEntries = async () => { + // try { + // await invoke('delete_all_history'); + // } catch (error) { + // console.error('Failed to delete all entries:', error); + // } + // }; + + const openSettings = () => { + navigateTo("/settings"); + }; + + // const pasteAsPlainText = async (item?: HistoryItem) => { + // if (!item) return; + // try { + // await invoke('paste_as_plain_text', { content: item.content }); + // } catch (error) { + // console.error('Failed to paste as plain text:', error); + // } + // }; + + // const openTextEditor = (item?: HistoryItem) => { + // if (!item) return; + // // Implement logic to open text editor with the content + // // This might use Nuxt router or a modal based on your app architecture + // }; + + // const rotateImage = async (item?: HistoryItem) => { + // if (!item || item.content_type !== ContentType.Image) return; + // try { + // await invoke('rotate_image', { path: item.file_path }); + // } catch (error) { + // console.error('Failed to rotate image:', error); + // } + // }; + + // const openImageResizer = (item?: HistoryItem) => { + // if (!item || item.content_type !== ContentType.Image) return; + // // Implement logic to open image resizer UI for this image + // }; + + // const compressImage = async (item?: HistoryItem) => { + // if (!item || item.content_type !== ContentType.Image) return; + // try { + // await invoke('compress_image', { path: item.file_path }); + // } catch (error) { + // console.error('Failed to compress image:', error); + // } + // }; + + // const openFile = async (item?: HistoryItem) => { + // if (!item || item.content_type !== ContentType.File) return; + // try { + // await invoke('open_file', { path: item.file_path }); + // } catch (error) { + // console.error('Failed to open file:', error); + // } + // }; + + // const compressFile = async (item?: HistoryItem) => { + // if (!item || item.content_type !== ContentType.File) return; + // try { + // await invoke('compress_file', { path: item.file_path }); + // } catch (error) { + // console.error('Failed to compress file:', error); + // } + // }; + + // const openInBrowser = async (item?: HistoryItem) => { + // if (!item || item.content_type !== ContentType.Link) return; + // try { + // await invoke('open_url', { url: item.content }); + // } catch (error) { + // console.error('Failed to open URL in browser:', error); + // } + // }; + + // const copyColorFormat = async (item?: HistoryItem, format: 'hex' | 'rgba' | 'hsla' = 'hex') => { + // if (!item || item.content_type !== ContentType.Color) return; + // try { + // const formattedColor = await invoke('get_color_format', { + // color: item.content, + // format + // }); + // await writeText(formattedColor as string); + // } catch (error) { + // console.error(`Failed to copy color as ${format}:`, error); + // } + // }; + + return { + handleAction, + isProcessing, + }; +} diff --git a/composables/useAppControl.ts b/composables/useAppControl.ts new file mode 100644 index 0000000..3087696 --- /dev/null +++ b/composables/useAppControl.ts @@ -0,0 +1,12 @@ +import { app, window } from "@tauri-apps/api"; + +export function useAppControl() { + const hideApp = async (): Promise => { + await app.hide(); + await window.getCurrentWindow().hide(); + }; + + return { + hideApp + }; +} \ No newline at end of file diff --git a/lib/selectedResult.ts b/lib/selectedResult.ts deleted file mode 100644 index e53411b..0000000 --- a/lib/selectedResult.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { HistoryItem } from '~/types/types' - -interface GroupedHistory { - label: string - items: HistoryItem[] -} - -export const selectedGroupIndex = ref(0) -export const selectedItemIndex = ref(0) -export const selectedElement = ref(null) - -export const useSelectedResult = (groupedHistory: Ref) => { - const selectedItem = computed(() => { - const group = groupedHistory.value[selectedGroupIndex.value] - return group?.items[selectedItemIndex.value] ?? null - }) - - const isSelected = (groupIndex: number, itemIndex: number): boolean => { - return selectedGroupIndex.value === groupIndex && selectedItemIndex.value === itemIndex - } - - const selectNext = (): void => { - const currentGroup = groupedHistory.value[selectedGroupIndex.value] - if (selectedItemIndex.value < currentGroup.items.length - 1) { - selectedItemIndex.value++ - } else if (selectedGroupIndex.value < groupedHistory.value.length - 1) { - selectedGroupIndex.value++ - selectedItemIndex.value = 0 - } - } - - const selectPrevious = (): void => { - if (selectedItemIndex.value > 0) { - selectedItemIndex.value-- - } else if (selectedGroupIndex.value > 0) { - selectedGroupIndex.value-- - selectedItemIndex.value = groupedHistory.value[selectedGroupIndex.value].items.length - 1 - } - } - - const selectItem = (groupIndex: number, itemIndex: number): void => { - selectedGroupIndex.value = groupIndex - selectedItemIndex.value = itemIndex - } - - return { - selectedItem, - isSelected, - selectNext, - selectPrevious, - selectItem, - selectedElement - } -} \ No newline at end of file diff --git a/nuxt.config.ts b/nuxt.config.ts index b10de45..38ff523 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -1,22 +1,24 @@ -// https://nuxt.com/docs/api/configuration/nuxt-config -export default defineNuxtConfig({ - devtools: { enabled: false }, - compatibilityDate: "2024-07-04", - ssr: false, - app: { - head: { - charset: "utf-8", - viewport: - "width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0", - }, - }, - vite: { - css: { - preprocessorOptions: { - scss: { - api: "modern-compiler", - }, - }, - }, - }, -}); +// https://nuxt.com/docs/api/configuration/nuxt-config +export default defineNuxtConfig({ + devtools: { enabled: false }, + compatibilityDate: "2024-07-04", + ssr: false, + + app: { + head: { + charset: "utf-8", + viewport: + "width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0", + }, + }, + + vite: { + css: { + preprocessorOptions: { + scss: { + api: "modern-compiler", + }, + }, + }, + }, +}); \ No newline at end of file diff --git a/package.json b/package.json index 47cf12d..c5fe834 100644 --- a/package.json +++ b/package.json @@ -1,28 +1,28 @@ -{ - "name": "nuxt-app", - "private": true, - "type": "module", - "scripts": { - "build": "tauri build", - "dev": "tauri dev", - "generate": "nuxt generate", - "preview": "nuxt preview", - "postinstall": "nuxt prepare" - }, - "dependencies": { - "@tauri-apps/api": "2.5.0", - "@tauri-apps/cli": "2.5.0", - "@tauri-apps/plugin-autostart": "2.3.0", - "@tauri-apps/plugin-os": "2.2.1", - "nuxt": "3.17.4", - "overlayscrollbars": "2.11.3", - "overlayscrollbars-vue": "0.5.9", - "sass-embedded": "1.89.0", - "uuid": "11.1.0", - "vue": "3.5.15", - "@waradu/keyboard": "4.2.0" - }, - "overrides": { - "chokidar": "^3.6.0" - } -} +{ + "name": "nuxt-app", + "private": true, + "type": "module", + "scripts": { + "build": "tauri build", + "dev": "tauri dev", + "generate": "nuxt generate", + "preview": "nuxt preview", + "postinstall": "nuxt prepare" + }, + "dependencies": { + "@tauri-apps/api": "2.5.0", + "@tauri-apps/cli": "2.5.0", + "@tauri-apps/plugin-autostart": "2.4.0", + "@tauri-apps/plugin-os": "2.2.2", + "nuxt": "3.17.5", + "overlayscrollbars": "2.11.4", + "overlayscrollbars-vue": "0.5.9", + "sass-embedded": "1.89.2", + "uuid": "11.1.0", + "vue": "3.5.17", + "@waradu/keyboard": "4.3.0" + }, + "overrides": { + "chokidar": "^3.6.0" + } +} diff --git a/pages/index.vue b/pages/index.vue index 98efb40..43ddcd4 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -1,850 +1,946 @@ - - - - - + + + + + diff --git a/pages/settings.vue b/pages/settings.vue index a114774..bb5ae0b 100644 --- a/pages/settings.vue +++ b/pages/settings.vue @@ -1,233 +1,209 @@ - - - - - + + + + + diff --git a/plugins/history.ts b/plugins/history.ts index 2bd84c2..29275c6 100644 --- a/plugins/history.ts +++ b/plugins/history.ts @@ -1,61 +1,61 @@ -import { invoke } from "@tauri-apps/api/core"; -import type { HistoryItem } from "~/types/types"; - -export default defineNuxtPlugin(() => { - return { - provide: { - history: { - async getHistory(): Promise { - return await invoke("get_history"); - }, - - async addHistoryItem(item: HistoryItem): Promise { - await invoke("add_history_item", { item }); - }, - - async searchHistory(query: string): Promise { - try { - return await invoke("search_history", { query }); - } catch (error) { - console.error("Error searching history:", error); - return []; - } - }, - - async loadHistoryChunk( - offset: number, - limit: number - ): Promise { - try { - return await invoke("load_history_chunk", { - offset, - limit, - }); - } catch (error) { - console.error("Error loading history chunk:", error); - return []; - } - }, - - async deleteHistoryItem(id: string): Promise { - await invoke("delete_history_item", { id }); - }, - - async clearHistory(): Promise { - await invoke("clear_history"); - }, - - async writeAndPaste(data: { - content: string; - contentType: string; - }): Promise { - await invoke("write_and_paste", data); - }, - - async readImage(data: { filename: string }): Promise { - return await invoke("read_image", data); - }, - }, - }, - }; -}); +import { invoke } from "@tauri-apps/api/core"; +import type { HistoryItem } from "~/types/types"; + +export default defineNuxtPlugin(() => { + return { + provide: { + history: { + async getHistory(): Promise { + return await invoke("get_history"); + }, + + async addHistoryItem(item: HistoryItem): Promise { + await invoke("add_history_item", { item }); + }, + + async searchHistory(query: string): Promise { + try { + return await invoke("search_history", { query }); + } catch (error) { + console.error("Error searching history:", error); + return []; + } + }, + + async loadHistoryChunk( + offset: number, + limit: number + ): Promise { + try { + return await invoke("load_history_chunk", { + offset, + limit, + }); + } catch (error) { + console.error("Error loading history chunk:", error); + return []; + } + }, + + async deleteHistoryItem(id: string): Promise { + await invoke("delete_history_item", { id }); + }, + + async clearHistory(): Promise { + await invoke("clear_history"); + }, + + async writeAndPaste(data: { + content: string; + contentType: string; + }): Promise { + await invoke("write_and_paste", data); + }, + + async readImage(data: { filename: string }): Promise { + return await invoke("read_image", data); + }, + }, + }, + }; +}); diff --git a/plugins/keyboard.ts b/plugins/keyboard.ts new file mode 100644 index 0000000..71341ee --- /dev/null +++ b/plugins/keyboard.ts @@ -0,0 +1,27 @@ +import { platform } from "@tauri-apps/plugin-os"; +import { useKeyboard, Key } from "@waradu/keyboard"; + +export default defineNuxtPlugin(async (nuxtApp) => { + const keyboardInstance = useKeyboard(); + let currentOS = "windows"; + try { + const osName = await Promise.resolve(platform()); + currentOS = osName.toLowerCase().includes("mac") ? "macos" : "windows"; + } catch (error) { + console.error("Error detecting platform:", error); + } + + // Defer initialization until the app is mounted + nuxtApp.hook('app:mounted', () => { + keyboardInstance.init(); + }); + + nuxtApp.provide('keyboard', { + listen: keyboardInstance.listen.bind(keyboardInstance), + init: keyboardInstance.init.bind(keyboardInstance), + Key, + currentOS, + // Provide a clear method if users need to manually clear all listeners from the instance + clearAll: keyboardInstance.clear ? keyboardInstance.clear.bind(keyboardInstance) : () => { console.warn('@waradu/keyboard instance does not have a clear method'); } + }); +}); diff --git a/plugins/selectedResult.ts b/plugins/selectedResult.ts new file mode 100644 index 0000000..d3a63b1 --- /dev/null +++ b/plugins/selectedResult.ts @@ -0,0 +1,68 @@ +import { ref, computed } from 'vue'; +import type { HistoryItem } from '~/types/types'; + +interface GroupedHistory { + label: string; + items: HistoryItem[]; +} + +const selectedGroupIndex = ref(0); +const selectedItemIndex = ref(0); +const selectedElement = ref(null); + +const useSelectedResult = (groupedHistory: Ref) => { + const selectedItem = computed(() => { + const group = groupedHistory.value[selectedGroupIndex.value]; + return group?.items[selectedItemIndex.value] ?? undefined; + }); + + const isSelected = (groupIndex: number, itemIndex: number): boolean => { + return selectedGroupIndex.value === groupIndex && selectedItemIndex.value === itemIndex; + }; + + const selectNext = (): void => { + const currentGroup = groupedHistory.value[selectedGroupIndex.value]; + if (selectedItemIndex.value < currentGroup.items.length - 1) { + selectedItemIndex.value++; + } else if (selectedGroupIndex.value < groupedHistory.value.length - 1) { + selectedGroupIndex.value++; + selectedItemIndex.value = 0; + } + }; + + const selectPrevious = (): void => { + if (selectedItemIndex.value > 0) { + selectedItemIndex.value--; + } else if (selectedGroupIndex.value > 0) { + selectedGroupIndex.value--; + selectedItemIndex.value = groupedHistory.value[selectedGroupIndex.value].items.length - 1; + } + }; + + const selectItem = (groupIndex: number, itemIndex: number): void => { + selectedGroupIndex.value = groupIndex; + selectedItemIndex.value = itemIndex; + }; + + return { + selectedItem, + isSelected, + selectNext, + selectPrevious, + selectItem, + selectedElement + }; +}; + +export default defineNuxtPlugin(() => { + return { + provide: { + selectedResult: { + selectedGroupIndex, + selectedItemIndex, + selectedElement, + useSelectedResult + } + } + }; +}); \ No newline at end of file diff --git a/plugins/settings.ts b/plugins/settings.ts index 8e2fcf2..fe4cfee 100644 --- a/plugins/settings.ts +++ b/plugins/settings.ts @@ -1,17 +1,17 @@ -import { invoke } from "@tauri-apps/api/core"; - -export default defineNuxtPlugin(() => { - return { - provide: { - settings: { - async getSetting(key: string): Promise { - return await invoke("get_setting", { key }); - }, - - async saveSetting(key: string, value: string): Promise { - await invoke("save_setting", { key, value }); - }, - }, - }, - }; -}); +import { invoke } from "@tauri-apps/api/core"; + +export default defineNuxtPlugin(() => { + return { + provide: { + settings: { + async getSetting(key: string): Promise { + return await invoke("get_setting", { key }); + }, + + async saveSetting(key: string, value: string): Promise { + await invoke("save_setting", { key, value }); + }, + }, + }, + }; +}); diff --git a/public/back_arrow.svg b/public/back_arrow.svg index e4c3012..1c43ff6 100644 --- a/public/back_arrow.svg +++ b/public/back_arrow.svg @@ -1,7 +1,7 @@ - - - - - - + + + + + + \ No newline at end of file diff --git a/src-tauri/.gitignore b/src-tauri/.gitignore index 502406b..489be32 100644 --- a/src-tauri/.gitignore +++ b/src-tauri/.gitignore @@ -1,4 +1,4 @@ -# Generated by Cargo -# will have compiled files and executables -/target/ -/gen/schemas +# Generated by Cargo +# will have compiled files and executables +/target/ +/gen/schemas diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 0046a72..ce2f11c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aho-corasick" @@ -49,9 +49,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-tzdata" @@ -70,9 +70,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "applications" @@ -96,7 +96,7 @@ dependencies = [ "serde_derive", "serde_json", "tauri-icns", - "thiserror 1.0.63", + "thiserror 1.0.69", "walkdir", "winapi", "windows-icons", @@ -120,7 +120,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -131,30 +131,27 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "ashpd" -version = "0.9.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe7e0dd0ac5a401dc116ed9f9119cf9decc625600474cb41f0fc0a0050abc9a" +checksum = "6cbdf310d77fd3aaee6ea2093db7011dc2d35d2eb3481e5607f1f8d942ed99df" dependencies = [ "enumflags2", "futures-channel", "futures-util", - "rand 0.8.5", + "rand 0.9.1", "raw-window-handle", "serde", "serde_repr", "tokio", "url", - "wayland-backend", - "wayland-client", - "wayland-protocols", "zbus", ] [[package]] name = "async-broadcast" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" dependencies = [ "event-listener", "event-listener-strategy", @@ -162,68 +159,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-channel" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-io" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" -dependencies = [ - "async-lock", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix", - "slab", - "tracing", - "windows-sys 0.52.0", -] - -[[package]] -name = "async-lock" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" -dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-process" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7eda79bbd84e29c2b308d1dc099d7de8dcc7035e48f4bf5dc4a531a44ff5e2a" -dependencies = [ - "async-channel", - "async-io", - "async-lock", - "async-signal", - "async-task", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "rustix", - "tracing", - "windows-sys 0.52.0", -] - [[package]] name = "async-recursion" version = "1.1.1" @@ -232,49 +167,25 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", -] - -[[package]] -name = "async-signal" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb3634b73397aa844481f814fad23bbf07fdb0eabec10f2eb95e58944b1ec32" -dependencies = [ - "async-io", - "async-lock", - "atomic-waker", - "cfg-if", - "futures-core", - "futures-io", - "rustix", - "signal-hook-registry", - "slab", - "windows-sys 0.52.0", + "syn 2.0.101", ] -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] name = "atk" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4af014b17dd80e8af9fa689b2d4a211ddba6eb583c1622f35d0cb543f6b17e4" +checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b" dependencies = [ "atk-sys", "glib", @@ -283,9 +194,9 @@ dependencies = [ [[package]] name = "atk-sys" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "251e0b7d90e33e0ba930891a505a9a35ece37b2dd37a14f3ffc306c13b980009" +checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086" dependencies = [ "glib-sys", "gobject-sys", @@ -315,21 +226,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f012b8cc0c850f34117ec8252a44418f2e34a2cf501de89e29b241ae5f79471" dependencies = [ "dirs 4.0.0", - "thiserror 1.0.63", + "thiserror 1.0.69", "winreg 0.10.1", ] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "av1-grain" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" +checksum = "4f3efb2ca85bc610acfa917b5aaa36f3fcbebed5b3182d7f877b02531c4b80c8" dependencies = [ "anyhow", "arrayvec", @@ -341,26 +252,26 @@ dependencies = [ [[package]] name = "avif-serialize" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e335041290c43101ca215eed6f43ec437eb5a42125573f600fc3fa42b9bddd62" +checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e" dependencies = [ "arrayvec", ] [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -377,9 +288,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] name = "bit-set" @@ -419,9 +330,9 @@ dependencies = [ [[package]] name = "bitstream-io" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcde5f311c85b8ca30c2e4198d4326bc342c76541590106f5fa4a50946ea499" +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" [[package]] name = "block" @@ -438,25 +349,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7" -dependencies = [ - "objc-sys", -] - -[[package]] -name = "block2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e58aa60e59d8dbfcc36138f5f18be5f24394d33b38b24f7fd0b1caa33095f22f" -dependencies = [ - "block-sys", - "objc2 0.5.2", -] - [[package]] name = "block2" version = "0.5.1" @@ -468,24 +360,11 @@ dependencies = [ [[package]] name = "block2" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d59b4c170e16f0405a2e95aff44432a0d41aa97675f3d52623effe95792a037" -dependencies = [ - "objc2 0.6.0", -] - -[[package]] -name = "blocking" -version = "1.6.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2" dependencies = [ - "async-channel", - "async-task", - "futures-io", - "futures-lite", - "piper", + "objc2 0.6.1", ] [[package]] @@ -501,9 +380,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "4.0.1" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" +checksum = "a334ef7c9e23abf0ce748e8cd309037da93e606ad52eb372e4ce327a0dcfbdfd" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -522,21 +401,21 @@ dependencies = [ [[package]] name = "built" -version = "0.7.4" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "236e6289eda5a812bc6b53c3b024039382a2895fbbeef2d748b2931546d392c4" +checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" [[package]] name = "bytemuck" -version = "1.16.3" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" [[package]] name = "byteorder" @@ -552,9 +431,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.7.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" dependencies = [ "serde", ] @@ -570,7 +449,7 @@ dependencies = [ "glib", "libc", "once_cell", - "thiserror 1.0.63", + "thiserror 1.0.69", ] [[package]] @@ -586,34 +465,34 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.7" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +checksum = "0da45bc31171d8d6960122e222a67740df867c1dd53b4d51caa297084c185cab" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ "serde", ] [[package]] name = "cargo_metadata" -version = "0.19.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ "camino", "cargo-platform", "semver", "serde", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.12", ] [[package]] @@ -628,9 +507,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.16" +version = "1.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" dependencies = [ "jobserver", "libc", @@ -693,15 +572,16 @@ dependencies = [ [[package]] name = "clipboard-rs" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd61885ce9f906c60f40d384b132fed04685f51d3da3576d27b8e4f274b6100d" +checksum = "afede46921767868c5c7f8f55202bdd8bec0bab6bc9605174200f45924f93c62" dependencies = [ "clipboard-win", "image", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", + "objc2 0.6.1", + "objc2-app-kit", + "objc2-foundation 0.3.1", + "windows 0.59.0", "x11rb", ] @@ -835,9 +715,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ "core-foundation-sys 0.8.7", "libc", @@ -899,7 +779,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ "bitflags 2.9.1", - "core-foundation 0.10.0", + "core-foundation 0.10.1", "core-graphics-types 0.2.0", "foreign-types 0.5.0", "libc", @@ -923,24 +803,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ "bitflags 2.9.1", - "core-foundation 0.10.0", + "core-foundation 0.10.1", "libc", ] [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crc" -version = "3.2.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" dependencies = [ "crc-catalog", ] @@ -962,18 +842,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -990,9 +870,9 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] @@ -1005,9 +885,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" [[package]] name = "crypto-common" @@ -1043,24 +923,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] name = "ctor" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" +checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] name = "darling" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ "darling_core", "darling_macro", @@ -1068,34 +948,34 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] name = "der" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "pem-rfc7468", @@ -1112,17 +992,6 @@ dependencies = [ "serde", ] -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "derive_arbitrary" version = "1.4.1" @@ -1131,20 +1000,20 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] name = "derive_more" -version = "0.99.18" +version = "0.99.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -1184,7 +1053,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", - "redox_users 0.4.5", + "redox_users 0.4.6", "winapi", ] @@ -1207,23 +1076,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] -name = "displaydoc" -version = "0.2.5" +name = "dispatch2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "1a0d569e003ff27784e0e14e4a594048698e0c0f0b66cabcb51511be55a7caa0" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", + "bitflags 2.9.1", + "block2 0.6.1", + "libc", + "objc2 0.6.1", ] [[package]] -name = "dlib" -version = "0.5.2" +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ - "libloading 0.8.6", + "proc-macro2", + "quote", + "syn 2.0.101", ] [[package]] @@ -1240,13 +1122,13 @@ dependencies = [ [[package]] name = "dlopen2_derive" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" +checksum = "788160fb30de9cdd857af31c6a2675904b16ece8fc2737b2c7127ba368c9d0f4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -1255,26 +1137,20 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" -[[package]] -name = "downcast-rs" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" - [[package]] name = "dpi" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" dependencies = [ "serde", ] [[package]] name = "dtoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" +checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" [[package]] name = "dtoa-short" @@ -1293,31 +1169,31 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "dyn-clone" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" +checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" dependencies = [ "serde", ] [[package]] name = "embed-resource" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbc6e0d8e0c03a655b53ca813f0463d2c956bc4db8138dbc89f120b066551e3" +checksum = "e8fe7d068ca6b3a5782ca5ec9afc244acd99dd441e4686a83b1c3973aba1d489" dependencies = [ "cc", "memchr", "rustc_version", "toml", "vswhom", - "winreg 0.52.0", + "winreg 0.55.0", ] [[package]] @@ -1328,9 +1204,9 @@ checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] @@ -1343,9 +1219,9 @@ checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" [[package]] name = "enumflags2" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" +checksum = "ba2f4b465f5318854c6f8dd686ede6c0a9dc67d4b1ac241cf0eb51521a309147" dependencies = [ "enumflags2_derive", "serde", @@ -1353,13 +1229,13 @@ dependencies = [ [[package]] name = "enumflags2_derive" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" +checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -1377,15 +1253,15 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" +checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" dependencies = [ "serde", "typeid", @@ -1393,19 +1269,19 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.9" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "error-code" -version = "3.2.0" +version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" [[package]] name = "etcetera" @@ -1420,9 +1296,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.3.1" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" dependencies = [ "concurrent-queue", "parking", @@ -1431,9 +1307,9 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ "event-listener", "pin-project-lite", @@ -1441,12 +1317,11 @@ dependencies = [ [[package]] name = "exr" -version = "1.72.0" +version = "1.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" dependencies = [ "bit_field", - "flume", "half", "lebe", "miniz_oxide", @@ -1457,15 +1332,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fdeflate" -version = "0.3.4" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ "simd-adler32", ] @@ -1482,9 +1357,9 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.24" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", @@ -1494,9 +1369,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.31" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", "miniz_oxide", @@ -1504,9 +1379,9 @@ dependencies = [ [[package]] name = "flume" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", @@ -1521,9 +1396,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "foreign-types" @@ -1552,7 +1427,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -1647,9 +1522,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.3.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" dependencies = [ "fastrand", "futures-core", @@ -1666,7 +1541,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -1710,9 +1585,9 @@ dependencies = [ [[package]] name = "gdk" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5ba081bdef3b75ebcdbfc953699ed2d7417d6bd853347a42a37d76406a33646" +checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691" dependencies = [ "cairo-rs", "gdk-pixbuf", @@ -1751,9 +1626,9 @@ dependencies = [ [[package]] name = "gdk-sys" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ff856cb3386dae1703a920f803abafcc580e9b5f711ca62ed1620c25b51ff2" +checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -1768,9 +1643,9 @@ dependencies = [ [[package]] name = "gdkwayland-sys" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a90fbf5c033c65d93792192a49a8efb5bb1e640c419682a58bb96f5ae77f3d4a" +checksum = "140071d506d223f7572b9f09b5e155afbd77428cd5cc7af8f2694c41d98dfe69" dependencies = [ "gdk-sys", "glib-sys", @@ -1782,9 +1657,9 @@ dependencies = [ [[package]] name = "gdkx11" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2ea8a4909d530f79921290389cbd7c34cb9d623bfe970eaae65ca5f9cd9cce" +checksum = "3caa00e14351bebbc8183b3c36690327eb77c49abc2268dd4bd36b856db3fbfe" dependencies = [ "gdk", "gdkx11-sys", @@ -1796,9 +1671,9 @@ dependencies = [ [[package]] name = "gdkx11-sys" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee8f00f4ee46cad2939b8990f5c70c94ff882c3028f3cc5abf950fa4ab53043" +checksum = "6e2e7445fe01ac26f11601db260dd8608fe172514eb63b3b5e261ea6b0f4428d" dependencies = [ "gdk-sys", "glib-sys", @@ -1829,11 +1704,11 @@ dependencies = [ [[package]] name = "gethostname" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fd4b8790c0792e3b11895efdf5f289ebe8b59107a6624f1cce68f24ff8c7035" +checksum = "fc257fdb4038301ce4b9cd1b3b51704509692bb3ff716a410cbd07925d9dae55" dependencies = [ - "rustix", + "rustix 1.0.7", "windows-targets 0.52.6", ] @@ -1850,25 +1725,29 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", + "js-sys", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] [[package]] @@ -1883,9 +1762,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "gio" @@ -1903,7 +1782,7 @@ dependencies = [ "once_cell", "pin-project-lite", "smallvec", - "thiserror 1.0.63", + "thiserror 1.0.69", ] [[package]] @@ -1939,7 +1818,7 @@ dependencies = [ "memchr", "once_cell", "smallvec", - "thiserror 1.0.63", + "thiserror 1.0.69", ] [[package]] @@ -1953,7 +1832,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -1980,11 +1859,11 @@ checksum = "b9247516746aa8e53411a0db9b62b0e24efbcf6a76e0ba73e5a91b512ddabed7" dependencies = [ "crossbeam-channel", "keyboard-types", - "objc2 0.6.0", - "objc2-app-kit 0.3.0", + "objc2 0.6.1", + "objc2-app-kit", "once_cell", "serde", - "thiserror 2.0.3", + "thiserror 2.0.12", "windows-sys 0.59.0", "x11rb", "xkeysym", @@ -2003,9 +1882,9 @@ dependencies = [ [[package]] name = "gtk" -version = "0.18.1" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93c4f5e0e20b60e10631a5f06da7fe3dda744b05ad0ea71fee2f47adf865890c" +checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" dependencies = [ "atk", "cairo-rs", @@ -2024,9 +1903,9 @@ dependencies = [ [[package]] name = "gtk-sys" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771437bf1de2c1c0b496c11505bdf748e26066bbe942dfc8f614c9460f6d7722" +checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" dependencies = [ "atk-sys", "cairo-sys-rs", @@ -2042,22 +1921,22 @@ dependencies = [ [[package]] name = "gtk3-macros" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6063efb63db582968fb7df72e1ae68aa6360dcfb0a75143f34fc7d616bad75e" +checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" dependencies = [ "proc-macro-crate 1.3.1", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] name = "h2" -version = "0.4.5" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" dependencies = [ "atomic-waker", "bytes", @@ -2065,7 +1944,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.3.0", + "indexmap 2.9.0", "slab", "tokio", "tokio-util", @@ -2074,9 +1953,9 @@ dependencies = [ [[package]] name = "half" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ "cfg-if", "crunchy", @@ -2090,15 +1969,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "hashbrown" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" dependencies = [ "allocator-api2", "equivalent", @@ -2111,7 +1984,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.4", ] [[package]] @@ -2128,21 +2001,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "hermit-abi" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" +checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" [[package]] name = "hex" @@ -2170,11 +2031,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2193,13 +2054,13 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", - "itoa 1.0.11", + "itoa 1.0.15", ] [[package]] @@ -2214,12 +2075,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", + "futures-core", "http", "http-body", "pin-project-lite", @@ -2227,9 +2088,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "humantime" @@ -2239,9 +2100,9 @@ checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" [[package]] name = "hyper" -version = "1.4.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ "bytes", "futures-channel", @@ -2250,7 +2111,7 @@ dependencies = [ "http", "http-body", "httparse", - "itoa 1.0.11", + "itoa 1.0.15", "pin-project-lite", "smallvec", "tokio", @@ -2259,11 +2120,10 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "futures-util", "http", "hyper", "hyper-util", @@ -2272,7 +2132,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "webpki-roots", + "webpki-roots 1.0.0", ] [[package]] @@ -2293,35 +2153,43 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", + "futures-core", "futures-util", "http", "http-body", "hyper", + "ipnet", + "libc", + "percent-encoding", "pin-project-lite", "socket2", + "system-configuration", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys 0.8.7", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core 0.61.2", ] [[package]] @@ -2343,33 +2211,24 @@ dependencies = [ "png", ] -[[package]] -name = "icrate" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb69199826926eb864697bddd27f73d9fddcffc004f5733131e15b465e30642" -dependencies = [ - "block2 0.4.0", - "objc2 0.5.2", -] - [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", @@ -2378,31 +2237,11 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -2410,67 +2249,54 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -2490,9 +2316,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -2523,9 +2349,9 @@ dependencies = [ [[package]] name = "image-webp" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e031e8e3d94711a9ccb5d6ea357439ef3dcbed361798bd4071dc4d9793fbe22f" +checksum = "b77d01e822461baa8409e156015a1d91735549f0f2c17691bd2d996bef238f7f" dependencies = [ "byteorder-lite", "quick-error", @@ -2533,9 +2359,9 @@ dependencies = [ [[package]] name = "imgref" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" +checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" [[package]] name = "include_dir" @@ -2569,12 +2395,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.3.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.4", "serde", ] @@ -2604,14 +2430,24 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] name = "ipnet" -version = "2.9.0" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] [[package]] name = "is-terminal" @@ -2619,7 +2455,7 @@ version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "hermit-abi 0.5.0", + "hermit-abi", "libc", "windows-sys 0.59.0", ] @@ -2650,9 +2486,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "javascriptcore-rs" @@ -2688,7 +2524,7 @@ dependencies = [ "combine", "jni-sys", "log", - "thiserror 1.0.63", + "thiserror 1.0.69", "walkdir", "windows-sys 0.45.0", ] @@ -2701,10 +2537,11 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ + "getrandom 0.3.3", "libc", ] @@ -2733,7 +2570,7 @@ dependencies = [ "jsonptr", "serde", "serde_json", - "thiserror 1.0.63", + "thiserror 1.0.69", ] [[package]] @@ -2805,25 +2642,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" dependencies = [ "gtk-sys", - "libloading 0.7.4", + "libloading", "once_cell", ] [[package]] name = "libc" -version = "0.2.169" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libfuzzer-sys" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" dependencies = [ "arbitrary", "cc", - "once_cell", ] [[package]] @@ -2836,21 +2672,11 @@ dependencies = [ "winapi", ] -[[package]] -name = "libloading" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" -dependencies = [ - "cfg-if", - "windows-targets 0.52.6", -] - [[package]] name = "libm" -version = "0.2.8" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" @@ -2860,7 +2686,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.9.1", "libc", - "redox_syscall 0.5.3", + "redox_syscall", ] [[package]] @@ -2876,15 +2702,21 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" -version = "0.7.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lnk" @@ -2902,9 +2734,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -2925,6 +2757,12 @@ dependencies = [ "imgref", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "mac" version = "0.1.1" @@ -3033,30 +2871,29 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "minisign-verify" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881" +checksum = "e856fdd13623a2f5f2f54676a4ee49502a96a80ef4a62bcedd23d52427c44d43" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ - "adler", + "adler2", "simd-adler32", ] [[package]] name = "mio" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ - "hermit-abi 0.3.9", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3069,22 +2906,22 @@ dependencies = [ "dpi", "gtk", "keyboard-types", - "objc2 0.6.0", - "objc2-app-kit 0.3.0", + "objc2 0.6.1", + "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.0", + "objc2-foundation 0.3.1", "once_cell", "png", "serde", - "thiserror 2.0.3", + "thiserror 2.0.12", "windows-sys 0.59.0", ] [[package]] name = "native-tls" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" dependencies = [ "libc", "log", @@ -3109,7 +2946,7 @@ dependencies = [ "ndk-sys", "num_enum", "raw-window-handle", - "thiserror 1.0.63", + "thiserror 1.0.69", ] [[package]] @@ -3135,12 +2972,13 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nix" -version = "0.27.1" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ "bitflags 2.9.1", "cfg-if", + "cfg_aliases", "libc", "memoffset", ] @@ -3219,7 +3057,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -3278,10 +3116,10 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "proc-macro-crate 2.0.0", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -3311,9 +3149,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3531f65190d9cff863b77a99857e74c314dd16bf56c538c4b57c7cbc3f3a6e59" +checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" dependencies = [ "objc2-encode", "objc2-exception-helper", @@ -3321,115 +3159,77 @@ dependencies = [ [[package]] name = "objc2-app-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" -dependencies = [ - "bitflags 2.9.1", - "block2 0.5.1", - "libc", - "objc2 0.5.2", - "objc2-core-data 0.2.2", - "objc2-core-image 0.2.2", - "objc2-foundation 0.2.2", - "objc2-quartz-core 0.2.2", -] - -[[package]] -name = "objc2-app-kit" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5906f93257178e2f7ae069efb89fbd6ee94f0592740b5f8a1512ca498814d0fb" +checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" dependencies = [ "bitflags 2.9.1", - "block2 0.6.0", + "block2 0.6.1", "libc", - "objc2 0.6.0", + "objc2 0.6.1", "objc2-cloud-kit", - "objc2-core-data 0.3.0", + "objc2-core-data", "objc2-core-foundation", "objc2-core-graphics", - "objc2-core-image 0.3.0", - "objc2-foundation 0.3.0", - "objc2-quartz-core 0.3.0", + "objc2-core-image", + "objc2-foundation 0.3.1", + "objc2-quartz-core 0.3.1", ] [[package]] name = "objc2-cloud-kit" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c1948a9be5f469deadbd6bcb86ad7ff9e47b4f632380139722f7d9840c0d42c" -dependencies = [ - "bitflags 2.9.1", - "objc2 0.6.0", - "objc2-foundation 0.3.0", -] - -[[package]] -name = "objc2-core-data" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +checksum = "17614fdcd9b411e6ff1117dfb1d0150f908ba83a7df81b1f118005fe0a8ea15d" dependencies = [ "bitflags 2.9.1", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", + "objc2 0.6.1", + "objc2-foundation 0.3.1", ] [[package]] name = "objc2-core-data" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f860f8e841f6d32f754836f51e6bc7777cd7e7053cf18528233f6811d3eceb4" +checksum = "291fbbf7d29287518e8686417cf7239c74700fd4b607623140a7d4a3c834329d" dependencies = [ "bitflags 2.9.1", - "objc2 0.6.0", - "objc2-foundation 0.3.0", + "objc2 0.6.1", + "objc2-foundation 0.3.1", ] [[package]] name = "objc2-core-foundation" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daeaf60f25471d26948a1c2f840e3f7d86f4109e3af4e8e4b5cd70c39690d925" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" dependencies = [ "bitflags 2.9.1", - "objc2 0.6.0", + "dispatch2 0.3.0", + "objc2 0.6.1", ] [[package]] name = "objc2-core-graphics" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dca602628b65356b6513290a21a6405b4d4027b8b250f0b98dddbb28b7de02" +checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" dependencies = [ "bitflags 2.9.1", - "objc2 0.6.0", + "dispatch2 0.3.0", + "objc2 0.6.1", "objc2-core-foundation", "objc2-io-surface", ] [[package]] name = "objc2-core-image" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal", -] - -[[package]] -name = "objc2-core-image" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ffa6bea72bf42c78b0b34e89c0bafac877d5f80bf91e159a5d96ea7f693ca56" +checksum = "79b3dc0cc4386b6ccf21c157591b34a7f44c8e75b064f85502901ab2188c007e" dependencies = [ - "objc2 0.6.0", - "objc2-foundation 0.3.0", + "objc2 0.6.1", + "objc2-foundation 0.3.1", ] [[package]] @@ -3455,32 +3255,31 @@ checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ "bitflags 2.9.1", "block2 0.5.1", - "dispatch", "libc", "objc2 0.5.2", ] [[package]] name = "objc2-foundation" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a21c6c9014b82c39515db5b396f91645182611c97d24637cf56ac01e5f8d998" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ "bitflags 2.9.1", - "block2 0.6.0", + "block2 0.6.1", "libc", - "objc2 0.6.0", + "objc2 0.6.1", "objc2-core-foundation", ] [[package]] name = "objc2-io-surface" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "161a8b87e32610086e1a7a9e9ec39f84459db7b3a0881c1f16ca5a2605581c19" +checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c" dependencies = [ "bitflags 2.9.1", - "objc2 0.6.0", + "objc2 0.6.1", "objc2-core-foundation", ] @@ -3498,14 +3297,14 @@ dependencies = [ [[package]] name = "objc2-osa-kit" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6788b04a18ea31e3dc3ab256b8546639e5bbae07c1a0dc4ea8615252bc6aee9a" +checksum = "26bb88504b5a050dbba515d2414607bf5e57dd56b107bc5f0351197a3e7bdc5d" dependencies = [ "bitflags 2.9.1", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", + "objc2 0.6.1", + "objc2-app-kit", + "objc2-foundation 0.3.1", ] [[package]] @@ -3523,61 +3322,61 @@ dependencies = [ [[package]] name = "objc2-quartz-core" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb3794501bb1bee12f08dcad8c61f2a5875791ad1c6f47faa71a0f033f20071" +checksum = "90ffb6a0cd5f182dc964334388560b12a57f7b74b3e2dec5e2722aa2dfb2ccd5" dependencies = [ "bitflags 2.9.1", - "objc2 0.6.0", - "objc2-foundation 0.3.0", + "objc2 0.6.1", + "objc2-foundation 0.3.1", ] [[package]] name = "objc2-ui-kit" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777a571be14a42a3990d4ebedaeb8b54cd17377ec21b92e8200ac03797b3bee1" +checksum = "25b1312ad7bc8a0e92adae17aa10f90aae1fb618832f9b993b022b591027daed" dependencies = [ "bitflags 2.9.1", - "objc2 0.6.0", + "objc2 0.6.1", "objc2-core-foundation", - "objc2-foundation 0.3.0", + "objc2-foundation 0.3.1", ] [[package]] name = "objc2-web-kit" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b717127e4014b0f9f3e8bba3d3f2acec81f1bde01f656823036e823ed2c94dce" +checksum = "91672909de8b1ce1c2252e95bbee8c1649c9ad9d14b9248b3d7b4c47903c47ad" dependencies = [ "bitflags 2.9.1", - "block2 0.6.0", - "objc2 0.6.0", - "objc2-app-kit 0.3.0", + "block2 0.6.1", + "objc2 0.6.1", + "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.0", + "objc2-foundation 0.3.1", ] [[package]] name = "object" -version = "0.36.3" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.21.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde51589ab56b20a6f686b2c68f7a0bd6add753d697abf720d63f8db3ab7b1ad" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "openssl" -version = "0.10.71" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ "bitflags 2.9.1", "cfg-if", @@ -3596,20 +3395,20 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.106" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", @@ -3635,27 +3434,28 @@ dependencies = [ [[package]] name = "os_info" -version = "3.9.2" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e6520c8cc998c5741ee68ec1dc369fc47e5f0ea5320018ecf2a1ccd6328f48b" +checksum = "d0e1ac5fde8d43c34139135df8ea9ee9465394b2d8d20f032d38998f64afffc3" dependencies = [ "log", + "plist", "serde", "windows-sys 0.52.0", ] [[package]] name = "osakit" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35366a452fce3f8947eb2f33226a133aaf0cacedef2af67ade348d58be7f85d0" +checksum = "732c71caeaa72c065bb69d7ea08717bd3f4863a4f451402fc9513e29dbd5261b" dependencies = [ - "icrate", - "objc2-foundation 0.2.2", + "objc2 0.6.1", + "objc2-foundation 0.3.1", "objc2-osa-kit", "serde", "serde_json", - "thiserror 1.0.63", + "thiserror 2.0.12", ] [[package]] @@ -3685,15 +3485,15 @@ dependencies = [ [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -3701,13 +3501,13 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.3", + "redox_syscall", "smallvec", "windows-targets 0.52.6", ] @@ -3721,7 +3521,7 @@ dependencies = [ "bitflags 1.3.2", "byteorder", "chrono", - "thiserror 1.0.63", + "thiserror 1.0.69", "widestring", ] @@ -3768,12 +3568,12 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ - "phf_macros 0.11.2", - "phf_shared 0.11.2", + "phf_macros 0.11.3", + "phf_shared 0.11.3", ] [[package]] @@ -3818,11 +3618,11 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "phf_shared 0.11.2", + "phf_shared 0.11.3", "rand 0.8.5", ] @@ -3842,15 +3642,15 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", + "phf_generator 0.11.3", + "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -3859,7 +3659,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" dependencies = [ - "siphasher", + "siphasher 0.3.11", ] [[package]] @@ -3868,23 +3668,23 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" dependencies = [ - "siphasher", + "siphasher 0.3.11", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher", + "siphasher 1.0.1", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -3892,17 +3692,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "piper" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - [[package]] name = "pkcs1" version = "0.7.5" @@ -3926,28 +3715,28 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "plist" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" +checksum = "eac26e981c03a6e53e0aee43c113e3202f5581d5360dae7bd2c70e800dd0451d" dependencies = [ "base64 0.22.1", - "indexmap 2.3.0", - "quick-xml 0.32.0", + "indexmap 2.9.0", + "quick-xml", "serde", "time", ] [[package]] name = "png" -version = "0.17.13" +version = "0.17.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -3957,18 +3746,12 @@ dependencies = [ ] [[package]] -name = "polling" -version = "3.7.2" +name = "potential_utf" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi 0.4.0", - "pin-project-lite", - "rustix", - "tracing", - "windows-sys 0.52.0", + "zerovec", ] [[package]] @@ -3979,11 +3762,11 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.7.35", + "zerocopy", ] [[package]] @@ -4008,7 +3791,16 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "toml_edit 0.20.2", + "toml_edit 0.20.7", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit 0.22.27", ] [[package]] @@ -4043,30 +3835,30 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" dependencies = [ "profiling-procmacros", ] [[package]] name = "profiling-procmacros" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" +checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" dependencies = [ "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -4134,72 +3926,76 @@ dependencies = [ "memchr", ] -[[package]] -name = "quick-xml" -version = "0.36.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" -dependencies = [ - "memchr", -] - [[package]] name = "quinn" -version = "0.11.3" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" dependencies = [ "bytes", + "cfg_aliases", "pin-project-lite", "quinn-proto", "quinn-udp", "rustc-hash", "rustls", "socket2", - "thiserror 1.0.63", + "thiserror 2.0.12", "tokio", "tracing", + "web-time", ] [[package]] name = "quinn-proto" -version = "0.11.8" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" dependencies = [ "bytes", - "rand 0.8.5", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.1", "ring", "rustc-hash", "rustls", + "rustls-pki-types", "slab", - "thiserror 1.0.63", + "thiserror 2.0.12", "tinyvec", "tracing", + "web-time", ] [[package]] name = "quinn-udp" -version = "0.5.4" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" +checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842" dependencies = [ + "cfg_aliases", "libc", "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "rand" version = "0.7.3" @@ -4232,7 +4028,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -4262,7 +4058,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -4280,17 +4076,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] name = "rand_core" -version = "0.9.0" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.1", - "zerocopy 0.8.14", + "getrandom 0.3.3", ] [[package]] @@ -4341,16 +4136,16 @@ dependencies = [ "rand_chacha 0.3.1", "simd_helpers", "system-deps", - "thiserror 1.0.63", + "thiserror 1.0.69", "v_frame", "wasm-bindgen", ] [[package]] name = "ravif" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2413fd96bd0ea5cdeeb37eaf446a22e6ed7b981d792828721e74ded1980a45c6" +checksum = "d6a5f31fcf7500f9401fea858ea4ab5525c99f2322cfcee732c0e6c74208c0c6" dependencies = [ "avif-serialize", "imgref", @@ -4405,31 +4200,22 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" dependencies = [ "bitflags 2.9.1", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "libredox", - "thiserror 1.0.63", + "thiserror 1.0.69", ] [[package]] @@ -4438,9 +4224,9 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "libredox", - "thiserror 2.0.3", + "thiserror 2.0.12", ] [[package]] @@ -4451,7 +4237,7 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax", ] @@ -4463,9 +4249,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -4480,9 +4266,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.15" +version = "0.12.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +checksum = "eabf4c97d9130e2bf606614eb937e86edac8292eaa6f422f995d7e8de1eb1813" dependencies = [ "base64 0.22.1", "bytes", @@ -4498,59 +4284,57 @@ dependencies = [ "hyper-rustls", "hyper-tls", "hyper-util", - "ipnet", "js-sys", "log", "mime", "native-tls", - "once_cell", "percent-encoding", "pin-project-lite", "quinn", "rustls", - "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", "tokio", "tokio-native-tls", "tokio-rustls", "tokio-util", "tower", + "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots", - "windows-registry", + "webpki-roots 1.0.0", ] [[package]] name = "rfd" -version = "0.15.0" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8af382a047821a08aa6bfc09ab0d80ff48d45d8726f7cd8e44891f7cb4a4278e" +checksum = "80c844748fdc82aae252ee4594a89b6e7ebef1063de7951545564cbc4e57075d" dependencies = [ "ashpd", - "block2 0.5.1", + "block2 0.6.1", + "dispatch2 0.2.0", "glib-sys", "gobject-sys", "gtk-sys", "js-sys", "log", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", + "objc2 0.6.1", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation 0.3.1", "raw-window-handle", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -4567,7 +4351,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom 0.2.16", "libc", "untrusted", "windows-sys 0.52.0", @@ -4575,9 +4359,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.6" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" dependencies = [ "const-oid", "digest", @@ -4601,68 +4385,75 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags 2.9.1", "errno", "libc", - "linux-raw-sys", - "windows-sys 0.52.0", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", ] [[package]] -name = "rustls" -version = "0.23.12" +name = "rustix" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "log", - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.59.0", ] [[package]] -name = "rustls-pemfile" -version = "2.1.3" +name = "rustls" +version = "0.23.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" dependencies = [ - "base64 0.22.1", + "log", + "once_cell", + "ring", "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", ] [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "web-time", + "zeroize", +] [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ "ring", "rustls-pki-types", @@ -4671,15 +4462,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" @@ -4692,18 +4483,18 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "schemars" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" dependencies = [ "dyn-clone", "indexmap 1.9.3", @@ -4716,22 +4507,16 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.87", + "syn 2.0.101", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.2.0" @@ -4753,9 +4538,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys 0.8.7", "libc", @@ -4763,9 +4548,9 @@ dependencies = [ [[package]] name = "select" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f9da09dc3f4dfdb6374cbffff7a2cffcec316874d4429899eefdc97b3b94dcd" +checksum = "5910c1d91bd7e6e178c0f8eb9e4ad01f814064b4a1c0ae3c906224a3cbf12879" dependencies = [ "bit-set", "html5ever", @@ -4794,9 +4579,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" dependencies = [ "serde", ] @@ -4812,9 +4597,9 @@ dependencies = [ [[package]] name = "serde-untagged" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2676ba99bd82f75cae5cbd2c8eda6fa0b8760f18978ea840e980dd5567b5c5b6" +checksum = "299d9c19d7d466db4ab10addd5703e4c615dec2a5a16dbbafe191045e87ee66e" dependencies = [ "erased-serde", "serde", @@ -4829,7 +4614,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -4840,7 +4625,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -4849,7 +4634,7 @@ version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ - "itoa 1.0.11", + "itoa 1.0.15", "memchr", "ryu", "serde", @@ -4857,20 +4642,20 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -4882,22 +4667,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.11", + "itoa 1.0.15", "ryu", "serde", ] [[package]] name = "serde_with" -version = "3.9.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.3.0", + "indexmap 2.9.0", "serde", "serde_derive", "serde_json", @@ -4907,14 +4692,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.9.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -4979,9 +4764,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] @@ -5017,6 +4802,12 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" version = "0.4.9" @@ -5028,18 +4819,18 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" dependencies = [ "serde", ] [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -5047,25 +4838,24 @@ dependencies = [ [[package]] name = "softbuffer" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d623bff5d06f60d738990980d782c8c866997d9194cfe79ecad00aa2f76826dd" +checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" dependencies = [ "bytemuck", "cfg_aliases", - "core-graphics 0.23.2", + "core-graphics 0.24.0", "foreign-types 0.5.0", "js-sys", "log", "objc2 0.5.2", - "objc2-app-kit 0.2.2", "objc2-foundation 0.2.2", "objc2-quartz-core 0.2.2", "raw-window-handle", - "redox_syscall 0.5.3", + "redox_syscall", "wasm-bindgen", "web-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5143,9 +4933,9 @@ dependencies = [ "futures-intrusive", "futures-io", "futures-util", - "hashbrown 0.15.2", + "hashbrown 0.15.4", "hashlink", - "indexmap 2.3.0", + "indexmap 2.9.0", "log", "memchr", "native-tls", @@ -5155,7 +4945,7 @@ dependencies = [ "serde_json", "sha2", "smallvec", - "thiserror 2.0.3", + "thiserror 2.0.12", "time", "tokio", "tokio-stream", @@ -5173,7 +4963,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -5196,7 +4986,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.87", + "syn 2.0.101", "tokio", "url", ] @@ -5225,7 +5015,7 @@ dependencies = [ "hex", "hkdf", "hmac", - "itoa 1.0.11", + "itoa 1.0.15", "log", "md-5", "memchr", @@ -5239,7 +5029,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.3", + "thiserror 2.0.12", "time", "tracing", "whoami", @@ -5266,7 +5056,7 @@ dependencies = [ "hkdf", "hmac", "home", - "itoa 1.0.11", + "itoa 1.0.15", "log", "md-5", "memchr", @@ -5278,7 +5068,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.3", + "thiserror 2.0.12", "time", "tracing", "whoami", @@ -5304,7 +5094,7 @@ dependencies = [ "serde", "serde_urlencoded", "sqlx-core", - "thiserror 2.0.3", + "thiserror 2.0.12", "time", "tracing", "url", @@ -5324,26 +5114,25 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "string_cache" -version = "0.8.7" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" dependencies = [ "new_debug_unreachable", - "once_cell", "parking_lot", - "phf_shared 0.10.0", + "phf_shared 0.11.3", "precomputed-hash", "serde", ] [[package]] name = "string_cache_codegen" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", + "phf_generator 0.11.3", + "phf_shared 0.11.3", "proc-macro2", "quote", ] @@ -5384,7 +5173,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -5417,9 +5206,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -5428,22 +5217,22 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -5496,7 +5285,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e59c1f38e657351a2e822eadf40d6a2ad4627b9c25557bc1180ec1b3295ef82" dependencies = [ "bitflags 2.9.1", - "core-foundation 0.10.0", + "core-foundation 0.10.1", "core-graphics 0.24.0", "crossbeam-channel", "dispatch", @@ -5512,9 +5301,9 @@ dependencies = [ "ndk", "ndk-context", "ndk-sys", - "objc2 0.6.0", - "objc2-app-kit 0.3.0", - "objc2-foundation 0.3.0", + "objc2 0.6.1", + "objc2-app-kit", + "objc2-foundation 0.3.1", "once_cell", "parking_lot", "raw-window-handle", @@ -5530,20 +5319,20 @@ dependencies = [ [[package]] name = "tao-macros" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec114582505d158b669b136e6851f85840c109819d77c42bb7c0709f727d18c2" +checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.101", ] [[package]] name = "tar" -version = "0.4.41" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" +checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" dependencies = [ "filetime", "libc", @@ -5568,7 +5357,7 @@ dependencies = [ "dunce", "embed_plist", "futures-util", - "getrandom 0.2.15", + "getrandom 0.2.16", "glob", "gtk", "heck 0.5.0", @@ -5579,9 +5368,9 @@ dependencies = [ "log", "mime", "muda", - "objc2 0.6.0", - "objc2-app-kit 0.3.0", - "objc2-foundation 0.3.0", + "objc2 0.6.1", + "objc2-app-kit", + "objc2-foundation 0.3.1", "objc2-ui-kit", "percent-encoding", "plist", @@ -5597,7 +5386,7 @@ dependencies = [ "tauri-runtime", "tauri-runtime-wry", "tauri-utils", - "thiserror 2.0.3", + "thiserror 2.0.12", "tokio", "tray-icon", "url", @@ -5648,9 +5437,9 @@ dependencies = [ "serde", "serde_json", "sha2", - "syn 2.0.87", + "syn 2.0.101", "tauri-utils", - "thiserror 2.0.3", + "thiserror 2.0.12", "time", "url", "uuid", @@ -5676,7 +5465,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", "tauri-codegen", "tauri-utils", ] @@ -5720,16 +5509,16 @@ dependencies = [ [[package]] name = "tauri-plugin-autostart" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58593aafcb03892dbf9998b35a96ead3b8e597435c7af46aff1654d076d5d03" +checksum = "8a9641831518c56775a364a8750e0eed8852adee87e0f11006d043b9ebba0bf5" dependencies = [ "auto-launch", "serde", "serde_json", "tauri", "tauri-plugin", - "thiserror 2.0.3", + "thiserror 2.0.12", ] [[package]] @@ -5744,7 +5533,7 @@ dependencies = [ "serde", "tauri", "tauri-plugin", - "thiserror 1.0.63", + "thiserror 1.0.69", ] [[package]] @@ -5761,7 +5550,7 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-plugin-fs", - "thiserror 2.0.3", + "thiserror 2.0.12", "url", ] @@ -5782,7 +5571,7 @@ dependencies = [ "tauri", "tauri-plugin", "tauri-utils", - "thiserror 2.0.3", + "thiserror 2.0.12", "toml", "url", ] @@ -5799,16 +5588,16 @@ dependencies = [ "serde_json", "tauri", "tauri-plugin", - "thiserror 2.0.3", + "thiserror 2.0.12", ] [[package]] name = "tauri-plugin-os" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "424f19432397850c2ddd42aa58078630c15287bbce3866eb1d90e7dbee680637" +checksum = "9009b6d2de65fe56bbcd31c3fe79ad03299d43f7a1b2841209f92bc8235d3efb" dependencies = [ - "gethostname 1.0.0", + "gethostname 1.0.2", "log", "os_info", "serde", @@ -5817,47 +5606,47 @@ dependencies = [ "sys-locale", "tauri", "tauri-plugin", - "thiserror 2.0.3", + "thiserror 2.0.12", ] [[package]] name = "tauri-plugin-prevent-default" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dbbe4f9038bcdbc035e07c06db4ddaf43672eb1a7c8b076109e9c6635b78368" +checksum = "d2ca8c73a98409d7faa73e10cfb3a0ef6a4e81e966f86769251c209fb5cc4043" dependencies = [ "bitflags 2.9.1", "itertools 0.14.0", "serde", "strum", "tauri", - "thiserror 2.0.3", + "thiserror 2.0.12", ] [[package]] name = "tauri-plugin-sql" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6ccca89ded6bd2ff49fdad9a5b34bcd624aa223fdfddbab83c85706ee3a4948" +checksum = "0502dfdc90b798752eb54d2d5ce0c82b3fa2972848899c40415ed54779473caa" dependencies = [ "futures-core", - "indexmap 2.3.0", + "indexmap 2.9.0", "log", "serde", "serde_json", "sqlx", "tauri", "tauri-plugin", - "thiserror 2.0.3", + "thiserror 2.0.12", "time", "tokio", ] [[package]] name = "tauri-plugin-updater" -version = "2.7.1" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f05c38afd77a4b8fd98e8fb6f1cdbb5fbb8a46ba181eb2758b05321e3c6209" +checksum = "b068673e9037376ca9906f99b00ae5f9e6eb62f456f900b4435c38d57cfa73e4" dependencies = [ "base64 0.22.1", "dirs 6.0.0", @@ -5877,11 +5666,11 @@ dependencies = [ "tauri", "tauri-plugin", "tempfile", - "thiserror 2.0.3", + "thiserror 2.0.12", "time", "tokio", "url", - "windows-sys 0.59.0", + "windows-sys 0.60.2", "zip", ] @@ -5896,13 +5685,13 @@ dependencies = [ "gtk", "http", "jni", - "objc2 0.6.0", + "objc2 0.6.1", "objc2-ui-kit", "raw-window-handle", "serde", "serde_json", "tauri-utils", - "thiserror 2.0.3", + "thiserror 2.0.12", "url", "windows 0.61.1", ] @@ -5917,9 +5706,9 @@ dependencies = [ "http", "jni", "log", - "objc2 0.6.0", - "objc2-app-kit 0.3.0", - "objc2-foundation 0.3.0", + "objc2 0.6.1", + "objc2-app-kit", + "objc2-foundation 0.3.1", "once_cell", "percent-encoding", "raw-window-handle", @@ -5953,7 +5742,7 @@ dependencies = [ "kuchikiki", "log", "memchr", - "phf 0.11.2", + "phf 0.11.3", "proc-macro2", "quote", "regex", @@ -5964,7 +5753,7 @@ dependencies = [ "serde_json", "serde_with", "swift-rs", - "thiserror 2.0.3", + "thiserror 2.0.12", "toml", "url", "urlpattern", @@ -5974,24 +5763,25 @@ dependencies = [ [[package]] name = "tauri-winres" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56eaa45f707bedf34d19312c26d350bc0f3c59a47e58e8adbeecdc850d2c13a0" +checksum = "e8d321dbc6f998d825ab3f0d62673e810c861aac2d0de2cc2c395328f1d113b4" dependencies = [ "embed-resource", + "indexmap 2.9.0", "toml", ] [[package]] name = "tempfile" -version = "3.12.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ - "cfg-if", "fastrand", + "getrandom 0.3.3", "once_cell", - "rustix", + "rustix 1.0.7", "windows-sys 0.59.0", ] @@ -6027,7 +5817,7 @@ dependencies = [ "nom", "percent-encoding", "regex", - "thiserror 1.0.63", + "thiserror 1.0.69", "url", ] @@ -6039,42 +5829,42 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.63", + "thiserror-impl 1.0.69", ] [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl 2.0.12", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -6095,7 +5885,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", - "itoa 1.0.11", + "itoa 1.0.15", "num-conv", "powerfmt", "serde", @@ -6121,9 +5911,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", @@ -6131,9 +5921,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ "tinyvec_macros", ] @@ -6171,7 +5961,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -6186,20 +5976,19 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ "rustls", - "rustls-pki-types", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -6208,9 +5997,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" dependencies = [ "bytes", "futures-core", @@ -6221,21 +6010,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.19" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.22", + "toml_edit 0.22.27", ] [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] @@ -6246,35 +6035,42 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.3.0", + "indexmap 2.9.0", "toml_datetime", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.3.0", + "indexmap 2.9.0", "toml_datetime", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.22.22" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.3.0", + "indexmap 2.9.0", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.24", + "toml_write", + "winnow 0.7.10", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "tower" version = "0.5.2" @@ -6290,6 +6086,24 @@ dependencies = [ "tower-service", ] +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.9.1", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -6304,9 +6118,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -6316,43 +6130,43 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", ] [[package]] name = "tray-icon" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d433764348e7084bad2c5ea22c96c71b61b17afe3a11645710f533bd72b6a2b5" +checksum = "9f7eee98ec5c90daf179d55c20a49d8c0d043054ce7c26336c09a24d31f14fa0" dependencies = [ "crossbeam-channel", "dirs 6.0.0", "libappindicator", "muda", - "objc2 0.6.0", - "objc2-app-kit 0.3.0", + "objc2 0.6.1", + "objc2-app-kit", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation 0.3.0", + "objc2-foundation 0.3.1", "once_cell", "png", "serde", - "thiserror 2.0.3", + "thiserror 2.0.12", "windows-sys 0.59.0", ] @@ -6364,15 +6178,15 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typeid" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "059d83cc991e7a42fc37bd50941885db0888e34209f8cfd9aab07ddec03bc9cf" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "uds_windows" @@ -6428,36 +6242,36 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-properties" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "untrusted" @@ -6467,9 +6281,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.10.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" dependencies = [ "base64 0.22.1", "flate2", @@ -6478,7 +6292,7 @@ dependencies = [ "rustls", "rustls-pki-types", "url", - "webpki-roots", + "webpki-roots 0.26.11", ] [[package]] @@ -6511,12 +6325,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -6529,7 +6337,7 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.3", "js-sys", "serde", "wasm-bindgen", @@ -6576,9 +6384,9 @@ dependencies = [ [[package]] name = "vswhom-sys" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3b17ae1f6c8a2b28506cd96d412eebf83b4a0ff2cbefeeb952f2f9dfa44ba18" +checksum = "fb067e4cbd1ff067d1df46c9194b5de0e98efd2810bbc95c5d5e5f25a3231150" dependencies = [ "cc", "libc", @@ -6617,9 +6425,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" -version = "0.13.3+wasi-0.2.2" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] @@ -6652,18 +6460,19 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] @@ -6686,7 +6495,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6702,9 +6511,9 @@ dependencies = [ [[package]] name = "wasm-streams" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" dependencies = [ "futures-util", "js-sys", @@ -6714,70 +6523,20 @@ dependencies = [ ] [[package]] -name = "wayland-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" -dependencies = [ - "cc", - "downcast-rs", - "rustix", - "scoped-tls", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-client" -version = "0.31.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3f45d1222915ef1fd2057220c1d9d9624b7654443ea35c3877f7a52bd0a5a2d" -dependencies = [ - "bitflags 2.9.1", - "rustix", - "wayland-backend", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols" -version = "0.32.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5755d77ae9040bb872a25026555ce4cb0ae75fd923e90d25fba07d81057de0" -dependencies = [ - "bitflags 2.9.1", - "wayland-backend", - "wayland-client", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.31.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" -dependencies = [ - "proc-macro2", - "quick-xml 0.36.2", - "quote", -] - -[[package]] -name = "wayland-sys" -version = "0.31.5" +name = "web-sys" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ - "dlib", - "log", - "pkg-config", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "web-sys" -version = "0.3.69" +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -6829,9 +6588,18 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.3" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.0", +] + +[[package]] +name = "webpki-roots" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" dependencies = [ "rustls-pki-types", ] @@ -6858,7 +6626,7 @@ checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -6867,24 +6635,24 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ae2d11c4a686e4409659d7891791254cf9286d3cfe0eef54df1523533d22295" dependencies = [ - "thiserror 2.0.3", + "thiserror 2.0.12", "windows 0.61.1", "windows-core 0.61.2", ] [[package]] name = "weezl" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" [[package]] name = "whoami" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" +checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" dependencies = [ - "redox_syscall 0.4.1", + "redox_syscall", "wasite", ] @@ -6931,10 +6699,10 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c" dependencies = [ - "objc2 0.6.0", - "objc2-app-kit 0.3.0", + "objc2 0.6.1", + "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.0", + "objc2-foundation 0.3.1", "raw-window-handle", "windows-sys 0.59.0", "windows-version", @@ -6947,7 +6715,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1" dependencies = [ "windows-core 0.59.0", - "windows-targets 0.53.0", + "windows-targets 0.53.2", ] [[package]] @@ -6972,15 +6740,6 @@ dependencies = [ "windows-core 0.61.2", ] -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-core" version = "0.59.0" @@ -6991,7 +6750,7 @@ dependencies = [ "windows-interface", "windows-result", "windows-strings 0.3.1", - "windows-targets 0.53.0", + "windows-targets 0.53.2", ] [[package]] @@ -7039,7 +6798,7 @@ checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -7050,7 +6809,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -7061,7 +6820,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] @@ -7082,13 +6841,13 @@ dependencies = [ [[package]] name = "windows-registry" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" +checksum = "b3bab093bdd303a1240bb99b8aba8ea8a69ee19d34c9e2ef9594e708a4878820" dependencies = [ + "windows-link", "windows-result", - "windows-strings 0.3.1", - "windows-targets 0.53.0", + "windows-strings 0.4.2", ] [[package]] @@ -7154,6 +6913,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.2", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -7202,9 +6970,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.0" +version = "0.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" dependencies = [ "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", @@ -7227,11 +6995,11 @@ dependencies = [ [[package]] name = "windows-version" -version = "0.1.1" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6998aa457c9ba8ff2fb9f13e9d2a930dabcea28f1d0ab94d687d8b3654844515" +checksum = "e04a5c6627e310a23ad2358483286c7df260c964eb2d003d8efd6d0f4e79265c" dependencies = [ - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -7434,9 +7202,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.24" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" dependencies = [ "memchr", ] @@ -7461,25 +7229,29 @@ dependencies = [ ] [[package]] -name = "wit-bindgen-rt" -version = "0.33.0" +name = "winreg" +version = "0.55.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" dependencies = [ - "bitflags 2.9.1", + "cfg-if", + "windows-sys 0.59.0", ] [[package]] -name = "write16" -version = "1.0.0" +name = "wit-bindgen-rt" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "wry" @@ -7488,7 +7260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c886a0a9d2a94fd90cfa1d929629b79cfefb1546e2c7430c63a47f0664c0e4e2" dependencies = [ "base64 0.22.1", - "block2 0.6.0", + "block2 0.6.1", "cookie", "crossbeam-channel", "dpi", @@ -7502,10 +7274,10 @@ dependencies = [ "kuchikiki", "libc", "ndk", - "objc2 0.6.0", - "objc2-app-kit 0.3.0", + "objc2 0.6.1", + "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.0", + "objc2-foundation 0.3.1", "objc2-ui-kit", "objc2-web-kit", "once_cell", @@ -7514,7 +7286,7 @@ dependencies = [ "sha2", "soup3", "tao-macros", - "thiserror 2.0.3", + "thiserror 2.0.12", "url", "webkit2gtk", "webkit2gtk-sys", @@ -7553,7 +7325,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" dependencies = [ "gethostname 0.4.3", - "rustix", + "rustix 0.38.44", "x11rb-protocol", ] @@ -7565,23 +7337,12 @@ checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" [[package]] name = "xattr" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" -dependencies = [ - "libc", - "linux-raw-sys", - "rustix", -] - -[[package]] -name = "xdg-home" -version = "1.2.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca91dcf8f93db085f3a0a29358cd0b9d670915468f4290e8b85d118a34211ab8" +checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e" dependencies = [ "libc", - "windows-sys 0.52.0", + "rustix 1.0.7", ] [[package]] @@ -7603,9 +7364,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -7615,45 +7376,39 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", "synstructure", ] [[package]] name = "zbus" -version = "4.0.1" +version = "5.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b8e3d6ae3342792a6cc2340e4394334c7402f3d793b390d2c5494a4032b3030" +checksum = "d3a7c7cee313d044fca3f48fa782cb750c79e4ca76ba7bc7718cd4024cdf6f68" dependencies = [ "async-broadcast", - "async-process", "async-recursion", "async-trait", - "derivative", "enumflags2", "event-listener", "futures-core", - "futures-sink", - "futures-util", + "futures-lite", "hex", "nix", "ordered-stream", - "rand 0.8.5", "serde", "serde_repr", - "sha1", - "static_assertions", "tokio", "tracing", "uds_windows", - "windows-sys 0.52.0", - "xdg-home", + "windows-sys 0.59.0", + "winnow 0.7.10", "zbus_macros", "zbus_names", "zvariant", @@ -7661,88 +7416,69 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "4.0.1" +version = "5.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a3e850ff1e7217a3b7a07eba90d37fe9bb9e89a310f718afcde5885ca9b6d7" +checksum = "a17e7e5eec1550f747e71a058df81a9a83813ba0f6a95f39c4e218bdc7ba366a" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "regex", - "syn 1.0.109", + "syn 2.0.101", + "zbus_names", + "zvariant", "zvariant_utils", ] [[package]] name = "zbus_names" -version = "3.0.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" dependencies = [ "serde", "static_assertions", + "winnow 0.7.10", "zvariant", ] [[package]] name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive 0.7.35", -] - -[[package]] -name = "zerocopy" -version = "0.8.14" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a367f292d93d4eab890745e75a778da40909cab4d6ff8173693812f79c4a2468" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" dependencies = [ - "zerocopy-derive 0.8.14", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", + "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.14" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3931cb58c62c13adec22e38686b559c86a30565e16ad6e8510a337cedc611e1" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", "synstructure", ] @@ -7752,11 +7488,22 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" dependencies = [ "yoke", "zerofrom", @@ -7765,28 +7512,25 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.101", ] [[package]] name = "zip" -version = "2.4.1" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938cc23ac49778ac8340e366ddc422b2227ea176edb447e23fc0627608dddadd" +checksum = "af7dcdb4229c0e79c2531a24de7726a0e980417a74fb4d030a35f535665439a0" dependencies = [ "arbitrary", "crc32fast", - "crossbeam-utils", - "displaydoc", - "indexmap 2.3.0", + "indexmap 2.9.0", "memchr", - "thiserror 2.0.3", ] [[package]] @@ -7806,47 +7550,51 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.4.13" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768" +checksum = "3e4a518c0ea2576f4da876349d7f67a7be489297cd77c2cf9e04c2e05fcd3974" dependencies = [ "zune-core", ] [[package]] name = "zvariant" -version = "4.0.0" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e09e8be97d44eeab994d752f341e67b3b0d80512a8b315a0671d47232ef1b65" +checksum = "9d30786f75e393ee63a21de4f9074d4c038d52c5b1bb4471f955db249f9dffb1" dependencies = [ "endi", "enumflags2", "serde", - "static_assertions", "url", + "winnow 0.7.10", "zvariant_derive", + "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "4.0.0" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a5857e2856435331636a9fbb415b09243df4521a267c5bedcd5289b4d5799e" +checksum = "75fda702cd42d735ccd48117b1630432219c0e9616bf6cb0f8350844ee4d9580" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.101", "zvariant_utils", ] [[package]] name = "zvariant_utils" -version = "1.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00bedb16a193cc12451873fee2a1bc6550225acece0e36f333e68326c73c8172" +checksum = "e16edfee43e5d7b553b77872d99bc36afdda75c223ca7ad5e3fbecd82ca5fc34" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "serde", + "static_assertions", + "syn 2.0.101", + "winnow 0.7.10", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 0d44eb8..4968514 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -4,7 +4,7 @@ version = "0.4.0" description = "Qopy" authors = ["pandadev"] edition = "2021" -rust-version = "1.80" +rust-version = "1.70" [build-dependencies] tauri-build = { version = "2.2.0", features = [] } @@ -15,14 +15,14 @@ tauri = { version = "2.5.1", features = [ "tray-icon", "image-png", ] } -tauri-plugin-sql = { version = "2.2.0", features = ["sqlite"] } -tauri-plugin-autostart = "2.3.0" -tauri-plugin-os = "2.2.1" -tauri-plugin-updater = "2.7.1" +tauri-plugin-sql = { version = "2.2.1", features = ["sqlite"] } +tauri-plugin-autostart = "2.4.0" +tauri-plugin-os = "2.2.2" +tauri-plugin-updater = "2.8.1" tauri-plugin-dialog = "2.2.2" tauri-plugin-fs = "2.3.0" tauri-plugin-clipboard = "2.1.11" -tauri-plugin-prevent-default = "2.1.0" +tauri-plugin-prevent-default = "2.1.1" tauri-plugin-global-shortcut = "2.2.1" tauri-plugin-aptabase = "1.0.0" sqlx = { version = "0.8.6", features = [ @@ -37,7 +37,7 @@ rdev = "0.5.3" rand = "0.9.1" base64 = "0.22.1" image = "0.25.6" -reqwest = { version = "0.12.15", features = ["json", "blocking"] } +reqwest = { version = "0.12.20", features = ["json", "blocking"] } url = "2.5.4" regex = "1.11.1" sha2 = "0.10.9" @@ -52,7 +52,7 @@ include_dir = "0.7.4" applications = { git = "https://github.com/HuakunShen/applications-rs", branch = "fix/win-app-detection" } glob = "0.3.2" meta_fetcher = "0.1.1" -parking_lot = "0.12.3" +parking_lot = "0.12.4" [features] custom-protocol = ["tauri/custom-protocol"] diff --git a/src-tauri/build.rs b/src-tauri/build.rs index d860e1e..2ba80a8 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -1,3 +1,3 @@ -fn main() { - tauri_build::build() -} +fn main() { + tauri_build::build() +} diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 883a577..af6ae62 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -1,34 +1,34 @@ -{ - "$schema": "../gen/schemas/desktop-schema.json", - "identifier": "default", - "description": "enables the default permissions", - "windows": [ - "main" - ], - "permissions": [ - "core:path:default", - "core:event:default", - "core:window:default", - "core:webview:default", - "core:app:default", - "core:resources:default", - "core:image:default", - "core:menu:default", - "core:tray:default", - "sql:allow-load", - "sql:allow-select", - "sql:allow-execute", - "autostart:allow-enable", - "autostart:allow-disable", - "autostart:allow-is-enabled", - "os:allow-os-type", - "core:app:allow-app-hide", - "core:app:allow-app-show", - "core:window:allow-hide", - "core:window:allow-show", - "core:window:allow-set-focus", - "core:window:allow-is-focused", - "core:window:allow-is-visible", - "fs:allow-read" - ] +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "default", + "description": "enables the default permissions", + "windows": [ + "main" + ], + "permissions": [ + "core:path:default", + "core:event:default", + "core:window:default", + "core:webview:default", + "core:app:default", + "core:resources:default", + "core:image:default", + "core:menu:default", + "core:tray:default", + "sql:allow-load", + "sql:allow-select", + "sql:allow-execute", + "autostart:allow-enable", + "autostart:allow-disable", + "autostart:allow-is-enabled", + "os:allow-os-type", + "core:app:allow-app-hide", + "core:app:allow-app-show", + "core:window:allow-hide", + "core:window:allow-show", + "core:window:allow-set-focus", + "core:window:allow-is-focused", + "core:window:allow-is-visible", + "fs:allow-read" + ] } \ No newline at end of file diff --git a/src-tauri/src/api/clipboard.rs b/src-tauri/src/api/clipboard.rs index f06881c..f93b458 100644 --- a/src-tauri/src/api/clipboard.rs +++ b/src-tauri/src/api/clipboard.rs @@ -1,280 +1,279 @@ -use tauri_plugin_aptabase::EventTracker; -use base64::{ engine::general_purpose::STANDARD, Engine }; -// use hyperpolyglot; -use lazy_static::lazy_static; -use rdev::{ simulate, EventType, Key }; -use regex::Regex; -use sqlx::SqlitePool; -use std::fs; -use std::sync::atomic::{ AtomicBool, Ordering }; -use std::{ thread, time::Duration }; -use tauri::{ AppHandle, Emitter, Listener, Manager }; -use tauri_plugin_clipboard::Clipboard; -use tokio::runtime::Runtime as TokioRuntime; -use url::Url; -use uuid::Uuid; - -use crate::db; -use crate::utils::commands::get_app_info; -use crate::utils::favicon::fetch_favicon_as_base64; -use crate::utils::types::{ ContentType, HistoryItem }; - -lazy_static! { - static ref IS_PROGRAMMATIC_PASTE: AtomicBool = AtomicBool::new(false); -} - -#[tauri::command] -pub async fn write_and_paste( - app_handle: AppHandle, - content: String, - content_type: String -) -> Result<(), String> { - let clipboard = app_handle.state::(); - - match content_type.as_str() { - "text" => clipboard.write_text(content).map_err(|e| e.to_string())?, - "link" => clipboard.write_text(content).map_err(|e| e.to_string())?, - "color" => clipboard.write_text(content).map_err(|e| e.to_string())?, - "image" => { - clipboard.write_image_base64(content).map_err(|e| e.to_string())?; - } - "files" => { - clipboard - .write_files_uris( - content - .split(", ") - .map(|file| file.to_string()) - .collect::>() - ) - .map_err(|e| e.to_string())?; - } - _ => { - return Err("Unsupported content type".to_string()); - } - } - - IS_PROGRAMMATIC_PASTE.store(true, Ordering::SeqCst); - - thread::spawn(|| { - thread::sleep(Duration::from_millis(100)); - - #[cfg(target_os = "macos")] - let modifier_key = Key::MetaLeft; - #[cfg(not(target_os = "macos"))] - let modifier_key = Key::ControlLeft; - - let events = vec![ - EventType::KeyPress(modifier_key), - EventType::KeyPress(Key::KeyV), - EventType::KeyRelease(Key::KeyV), - EventType::KeyRelease(modifier_key) - ]; - - for event in events { - if let Err(e) = simulate(&event) { - println!("Simulation error: {:?}", e); - } - thread::sleep(Duration::from_millis(20)); - } - }); - - tokio::spawn(async { - tokio::time::sleep(tokio::time::Duration::from_millis(500)).await; - IS_PROGRAMMATIC_PASTE.store(false, Ordering::SeqCst); - }); - - let _ = app_handle.track_event( - "clipboard_paste", - Some(serde_json::json!({ - "content_type": content_type - })) - ); - - Ok(()) -} - -pub fn setup(app: &AppHandle) { - let app_handle = app.clone(); - let runtime = TokioRuntime::new().expect("Failed to create Tokio runtime"); - - app_handle.clone().listen("plugin:clipboard://clipboard-monitor/update", move |_event| { - let app_handle = app_handle.clone(); - runtime.block_on(async move { - if IS_PROGRAMMATIC_PASTE.load(Ordering::SeqCst) { - return; - } - - let clipboard = app_handle.state::(); - let available_types = clipboard.available_types().unwrap(); - - let (app_name, app_icon) = get_app_info(); - - match get_pool(&app_handle).await { - Ok(pool) => { - if available_types.image { - println!("Handling image change"); - if let Ok(image_data) = clipboard.read_image_base64() { - let file_path = save_image_to_file(&app_handle, &image_data).await - .map_err(|e| e.to_string()) - .unwrap_or_else(|e| e); - let _ = db::history::add_history_item( - app_handle.clone(), - pool, - HistoryItem::new( - app_name, - ContentType::Image, - file_path, - None, - app_icon, - None - ) - ).await; - } - } else if available_types.files { - println!("Handling files change"); - if let Ok(files) = clipboard.read_files() { - for file in files { - let _ = db::history::add_history_item( - app_handle.clone(), - pool.clone(), - HistoryItem::new( - app_name.clone(), - ContentType::File, - file, - None, - app_icon.clone(), - None - ) - ).await; - } - } - } else if available_types.text { - println!("Handling text change"); - if let Ok(text) = clipboard.read_text() { - let text = text.to_string(); - let url_regex = Regex::new( - r"^https?://(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*)$" - ).unwrap(); - - if url_regex.is_match(&text) { - if let Ok(url) = Url::parse(&text) { - let favicon = match fetch_favicon_as_base64(url).await { - Ok(Some(f)) => Some(f), - _ => None, - }; - - let _ = db::history::add_history_item( - app_handle.clone(), - pool, - HistoryItem::new( - app_name, - ContentType::Link, - text, - favicon, - app_icon, - None - ) - ).await; - } - } else { - if text.is_empty() { - return; - } - - // Temporarily disabled code detection - /*if let Some(detection) = hyperpolyglot::detect_from_text(&text) { - let language = match detection { - hyperpolyglot::Detection::Heuristics(lang) => lang.to_string(), - _ => detection.language().to_string(), - }; - - let _ = db::history::add_history_item( - pool, - HistoryItem::new(app_name, ContentType::Code, text, None, app_icon, Some(language)) - ).await; - } else*/ if crate::utils::commands::detect_color(&text) { - let _ = db::history::add_history_item( - app_handle.clone(), - pool, - HistoryItem::new( - app_name, - ContentType::Color, - text, - None, - app_icon, - None - ) - ).await; - } else { - let _ = db::history::add_history_item( - app_handle.clone(), - pool, - HistoryItem::new( - app_name, - ContentType::Text, - text.clone(), - None, - app_icon, - None - ) - ).await; - } - } - } - } else { - println!("Unknown clipboard content type"); - } - } - Err(e) => { - println!("Failed to get database pool: {}", e); - } - } - - let _ = app_handle.emit("clipboard-content-updated", ()); - let _ = app_handle.track_event( - "clipboard_copied", - Some( - serde_json::json!({ - "content_type": if available_types.image { "image" } - else if available_types.files { "files" } - else if available_types.text { "text" } - else { "unknown" } - }) - ) - ); - }); - }); -} - -async fn get_pool( - app_handle: &AppHandle -) -> Result, Box> { - Ok(app_handle.state::()) -} - -#[tauri::command] -pub fn start_monitor(app_handle: AppHandle) -> Result<(), String> { - let clipboard = app_handle.state::(); - clipboard.start_monitor(app_handle.clone()).map_err(|e| e.to_string())?; - app_handle - .emit("plugin:clipboard://clipboard-monitor/status", true) - .map_err(|e| e.to_string())?; - Ok(()) -} - -async fn save_image_to_file( - app_handle: &AppHandle, - base64_data: &str -) -> Result> { - let app_data_dir = app_handle.path().app_data_dir().unwrap(); - let images_dir = app_data_dir.join("images"); - fs::create_dir_all(&images_dir)?; - - let file_name = format!("{}.png", Uuid::new_v4()); - let file_path = images_dir.join(&file_name); - - let bytes = STANDARD.decode(base64_data)?; - fs::write(&file_path, bytes)?; - - Ok(file_path.to_string_lossy().into_owned()) -} +use tauri_plugin_aptabase::EventTracker; +use base64::{ engine::general_purpose::STANDARD, Engine }; +// use hyperpolyglot; +use lazy_static::lazy_static; +use rdev::{ simulate, EventType, Key }; +use regex::Regex; +use sqlx::SqlitePool; +use std::fs; +use std::sync::atomic::{ AtomicBool, Ordering }; +use std::{ thread, time::Duration }; +use tauri::{ AppHandle, Emitter, Listener, Manager }; +use tauri_plugin_clipboard::Clipboard; +use tokio::runtime::Runtime as TokioRuntime; +use url::Url; +use uuid::Uuid; + +use crate::db; +use crate::utils::commands::get_app_info; +use crate::utils::favicon::fetch_favicon_as_base64; +use crate::utils::types::{ ContentType, HistoryItem }; + +lazy_static! { + static ref IS_PROGRAMMATIC_PASTE: AtomicBool = AtomicBool::new(false); +} + +#[tauri::command] +pub async fn write_and_paste( + app_handle: AppHandle, + content: String, + content_type: String +) -> Result<(), String> { + let clipboard = app_handle.state::(); + + match content_type.as_str() { + "text" => clipboard.write_text(content).map_err(|e| e.to_string())?, + "link" => clipboard.write_text(content).map_err(|e| e.to_string())?, + "color" => clipboard.write_text(content).map_err(|e| e.to_string())?, + "image" => { + clipboard.write_image_base64(content).map_err(|e| e.to_string())?; + } + "files" => { + clipboard + .write_files_uris( + content + .split(", ") + .map(|file| file.to_string()) + .collect::>() + ) + .map_err(|e| e.to_string())?; + } + _ => { + return Err("Unsupported content type".to_string()); + } + } + + IS_PROGRAMMATIC_PASTE.store(true, Ordering::SeqCst); + + thread::spawn(|| { + thread::sleep(Duration::from_millis(100)); + + #[cfg(target_os = "macos")] + let modifier_key = Key::MetaLeft; + #[cfg(not(target_os = "macos"))] + let modifier_key = Key::ControlLeft; + + let events = vec![ + EventType::KeyPress(modifier_key), + EventType::KeyPress(Key::KeyV), + EventType::KeyRelease(Key::KeyV), + EventType::KeyRelease(modifier_key) + ]; + + for event in events { + if let Err(e) = simulate(&event) { + println!("Simulation error: {:?}", e); + } + thread::sleep(Duration::from_millis(20)); + } + }); + + tokio::spawn(async { + tokio::time::sleep(tokio::time::Duration::from_millis(500)).await; + IS_PROGRAMMATIC_PASTE.store(false, Ordering::SeqCst); + }); + + let _ = app_handle.track_event( + "clipboard_paste", + Some(serde_json::json!({ + "content_type": content_type + })) + ); + + Ok(()) +} + +pub fn setup(app: &AppHandle) { + let app_handle = app.clone(); + let runtime = TokioRuntime::new().expect("Failed to create Tokio runtime"); + + app_handle.clone().listen("plugin:clipboard://clipboard-monitor/update", move |_event| { + let app_handle = app_handle.clone(); + runtime.block_on(async move { + if IS_PROGRAMMATIC_PASTE.load(Ordering::SeqCst) { + return; + } + + let clipboard = app_handle.state::(); + let available_types = clipboard.available_types().unwrap(); + + let (app_name, app_icon) = get_app_info(); + + match get_pool(&app_handle).await { + Ok(pool) => { + if available_types.image { + println!("Handling image change"); + if let Ok(image_data) = clipboard.read_image_base64() { + let file_path = save_image_to_file(&app_handle, &image_data).await + .map_err(|e| e.to_string()) + .unwrap_or_else(|e| e); + let _ = db::history::add_history_item( + app_handle.clone(), + pool, + HistoryItem::new( + app_name, + ContentType::Image, + file_path, + None, + app_icon, + None + ) + ).await; + } + } else if available_types.files { + println!("Handling files change"); + if let Ok(files) = clipboard.read_files() { + for file in files { + let _ = db::history::add_history_item( + app_handle.clone(), + pool.clone(), + HistoryItem::new( + app_name.clone(), + ContentType::File, + file, + None, + app_icon.clone(), + None + ) + ).await; + } + } + } else if available_types.text { + println!("Handling text change"); + if let Ok(text) = clipboard.read_text() { + let text = text.to_string(); + let url_regex = Regex::new( + r"^https?://(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*)$" + ).unwrap(); + + if url_regex.is_match(&text) { + if let Ok(url) = Url::parse(&text) { + let favicon = match fetch_favicon_as_base64(url).await { + Ok(Some(f)) => Some(f), + _ => None, + }; + + let _ = db::history::add_history_item( + app_handle.clone(), + pool, + HistoryItem::new( + app_name, + ContentType::Link, + text, + favicon, + app_icon, + None + ) + ).await; + } + } else { + if text.is_empty() { + return; + } + + // Temporarily disabled code detection + /*if let Some(detection) = hyperpolyglot::detect_from_text(&text) { + let language = match detection { + hyperpolyglot::Detection::Heuristics(lang) => lang.to_string(), + _ => detection.language().to_string(), + }; + + let _ = db::history::add_history_item( + pool, + HistoryItem::new(app_name, ContentType::Code, text, None, app_icon, Some(language)) + ).await; + } else*/ if crate::utils::commands::detect_color(&text) { + let _ = db::history::add_history_item( + app_handle.clone(), + pool, + HistoryItem::new( + app_name, + ContentType::Color, + text, + None, + app_icon, + None + ) + ).await; + } else { + let _ = db::history::add_history_item( + app_handle.clone(), + pool, + HistoryItem::new( + app_name, + ContentType::Text, + text.clone(), + None, + app_icon, + None + ) + ).await; + } + } + } + } else { + println!("Unknown clipboard content type"); + } + } + Err(e) => { + println!("Failed to get database pool: {}", e); + } + } + + let _ = app_handle.track_event( + "clipboard_copied", + Some( + serde_json::json!({ + "content_type": if available_types.image { "image" } + else if available_types.files { "files" } + else if available_types.text { "text" } + else { "unknown" } + }) + ) + ); + }); + }); +} + +async fn get_pool( + app_handle: &AppHandle +) -> Result, Box> { + Ok(app_handle.state::()) +} + +#[tauri::command] +pub fn start_monitor(app_handle: AppHandle) -> Result<(), String> { + let clipboard = app_handle.state::(); + clipboard.start_monitor(app_handle.clone()).map_err(|e| e.to_string())?; + app_handle + .emit("plugin:clipboard://clipboard-monitor/status", true) + .map_err(|e| e.to_string())?; + Ok(()) +} + +async fn save_image_to_file( + app_handle: &AppHandle, + base64_data: &str +) -> Result> { + let app_data_dir = app_handle.path().app_data_dir().unwrap(); + let images_dir = app_data_dir.join("images"); + fs::create_dir_all(&images_dir)?; + + let file_name = format!("{}.png", Uuid::new_v4()); + let file_path = images_dir.join(&file_name); + + let bytes = STANDARD.decode(base64_data)?; + fs::write(&file_path, bytes)?; + + Ok(file_path.to_string_lossy().into_owned()) +} diff --git a/src-tauri/src/api/hotkeys.rs b/src-tauri/src/api/hotkeys.rs index 6152ea0..d64aa8c 100644 --- a/src-tauri/src/api/hotkeys.rs +++ b/src-tauri/src/api/hotkeys.rs @@ -1,155 +1,155 @@ -use crate::utils::commands::center_window_on_current_monitor; -use crate::utils::keys::KeyCode; -use global_hotkey::{ - hotkey::{ Code, HotKey, Modifiers }, - GlobalHotKeyEvent, - GlobalHotKeyManager, - HotKeyState, -}; -use parking_lot::Mutex; -use std::str::FromStr; -use std::sync::Arc; -use tauri::{ AppHandle, Manager, Listener }; -use tauri_plugin_aptabase::EventTracker; - -#[derive(Default)] -struct HotkeyState { - manager: Option, - registered_hotkey: Option, -} - -unsafe impl Send for HotkeyState {} - -pub fn setup(app_handle: tauri::AppHandle) { - let state = Arc::new(Mutex::new(HotkeyState::default())); - let manager = match GlobalHotKeyManager::new() { - Ok(manager) => manager, - Err(err) => { - eprintln!("Failed to initialize hotkey manager: {:?}", err); - return; - } - }; - - { - let mut hotkey_state = state.lock(); - hotkey_state.manager = Some(manager); - } - - let rt = app_handle.state::(); - let initial_keybind = rt - .block_on(crate::db::settings::get_keybind(app_handle.clone())) - .expect("Failed to get initial keybind"); - - if let Err(e) = register_shortcut(&state, &initial_keybind) { - eprintln!("Error registering initial shortcut: {:?}", e); - } - - let state_clone = Arc::clone(&state); - app_handle.listen("update-shortcut", move |event| { - let payload_str = event.payload().replace("\\\"", "\""); - let trimmed_str = payload_str.trim_matches('"'); - unregister_current_hotkey(&state_clone); - - let payload: Vec = serde_json::from_str(trimmed_str).unwrap_or_default(); - if let Err(e) = register_shortcut(&state_clone, &payload) { - eprintln!("Error re-registering shortcut: {:?}", e); - } - }); - - let state_clone = Arc::clone(&state); - app_handle.listen("save_keybind", move |event| { - let payload_str = event.payload().to_string(); - unregister_current_hotkey(&state_clone); - - let payload: Vec = serde_json::from_str(&payload_str).unwrap_or_default(); - if let Err(e) = register_shortcut(&state_clone, &payload) { - eprintln!("Error registering saved shortcut: {:?}", e); - } - }); - - setup_hotkey_receiver(app_handle); -} - -fn setup_hotkey_receiver(app_handle: AppHandle) { - std::thread::spawn(move || { - loop { - match GlobalHotKeyEvent::receiver().recv() { - Ok(event) => { - if event.state == HotKeyState::Released { - continue; - } - handle_hotkey_event(&app_handle); - } - Err(e) => eprintln!("Error receiving hotkey event: {:?}", e), - } - } - }); -} - -fn unregister_current_hotkey(state: &Arc>) { - let mut hotkey_state = state.lock(); - if let Some(old_hotkey) = hotkey_state.registered_hotkey.take() { - if let Some(manager) = &hotkey_state.manager { - let _ = manager.unregister(old_hotkey); - } - } -} - -fn register_shortcut(state: &Arc>, shortcut: &[String]) -> Result<(), Box> { - let hotkey = parse_hotkey(shortcut)?; - let mut hotkey_state = state.lock(); - - if let Some(manager) = &hotkey_state.manager { - manager.register(hotkey.clone())?; - hotkey_state.registered_hotkey = Some(hotkey); - Ok(()) - } else { - Err("Hotkey manager not initialized".into()) - } -} - -fn parse_hotkey(shortcut: &[String]) -> Result> { - let mut modifiers = Modifiers::empty(); - let mut code = None; - - for part in shortcut { - match part.as_str() { - "ControlLeft" => modifiers |= Modifiers::CONTROL, - "AltLeft" => modifiers |= Modifiers::ALT, - "ShiftLeft" => modifiers |= Modifiers::SHIFT, - "MetaLeft" => modifiers |= Modifiers::META, - key => code = Some(Code::from(KeyCode::from_str(key)?)), - } - } - - let key_code = code.ok_or_else(|| "No valid key code found".to_string())?; - Ok(HotKey::new(Some(modifiers), key_code)) -} - -fn handle_hotkey_event(app_handle: &AppHandle) { - let window = app_handle.get_webview_window("main").unwrap(); - if window.is_visible().unwrap() { - window.hide().unwrap(); - } else { - window.set_always_on_top(true).unwrap(); - window.show().unwrap(); - window.set_focus().unwrap(); - - let window_clone = window.clone(); - std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_millis(100)); - window_clone.set_always_on_top(false).unwrap(); - }); - - center_window_on_current_monitor(&window); - } - - let _ = app_handle.track_event( - "hotkey_triggered", - Some( - serde_json::json!({ - "action": if window.is_visible().unwrap() { "hide" } else { "show" } - }) - ) - ); +use crate::utils::commands::center_window_on_current_monitor; +use crate::utils::keys::KeyCode; +use global_hotkey::{ + hotkey::{ Code, HotKey, Modifiers }, + GlobalHotKeyEvent, + GlobalHotKeyManager, + HotKeyState, +}; +use parking_lot::Mutex; +use std::str::FromStr; +use std::sync::Arc; +use tauri::{ AppHandle, Manager, Listener }; +use tauri_plugin_aptabase::EventTracker; + +#[derive(Default)] +struct HotkeyState { + manager: Option, + registered_hotkey: Option, +} + +unsafe impl Send for HotkeyState {} + +pub fn setup(app_handle: tauri::AppHandle) { + let state = Arc::new(Mutex::new(HotkeyState::default())); + let manager = match GlobalHotKeyManager::new() { + Ok(manager) => manager, + Err(err) => { + eprintln!("Failed to initialize hotkey manager: {:?}", err); + return; + } + }; + + { + let mut hotkey_state = state.lock(); + hotkey_state.manager = Some(manager); + } + + let rt = app_handle.state::(); + let initial_keybind = rt + .block_on(crate::db::settings::get_keybind(app_handle.clone())) + .expect("Failed to get initial keybind"); + + if let Err(e) = register_shortcut(&state, &initial_keybind) { + eprintln!("Error registering initial shortcut: {:?}", e); + } + + let state_clone = Arc::clone(&state); + app_handle.listen("update-shortcut", move |event| { + let payload_str = event.payload().replace("\\\"", "\""); + let trimmed_str = payload_str.trim_matches('"'); + unregister_current_hotkey(&state_clone); + + let payload: Vec = serde_json::from_str(trimmed_str).unwrap_or_default(); + if let Err(e) = register_shortcut(&state_clone, &payload) { + eprintln!("Error re-registering shortcut: {:?}", e); + } + }); + + let state_clone = Arc::clone(&state); + app_handle.listen("save_keybind", move |event| { + let payload_str = event.payload().to_string(); + unregister_current_hotkey(&state_clone); + + let payload: Vec = serde_json::from_str(&payload_str).unwrap_or_default(); + if let Err(e) = register_shortcut(&state_clone, &payload) { + eprintln!("Error registering saved shortcut: {:?}", e); + } + }); + + setup_hotkey_receiver(app_handle); +} + +fn setup_hotkey_receiver(app_handle: AppHandle) { + std::thread::spawn(move || { + loop { + match GlobalHotKeyEvent::receiver().recv() { + Ok(event) => { + if event.state == HotKeyState::Released { + continue; + } + handle_hotkey_event(&app_handle); + } + Err(e) => eprintln!("Error receiving hotkey event: {:?}", e), + } + } + }); +} + +fn unregister_current_hotkey(state: &Arc>) { + let mut hotkey_state = state.lock(); + if let Some(old_hotkey) = hotkey_state.registered_hotkey.take() { + if let Some(manager) = &hotkey_state.manager { + let _ = manager.unregister(old_hotkey); + } + } +} + +fn register_shortcut(state: &Arc>, shortcut: &[String]) -> Result<(), Box> { + let hotkey = parse_hotkey(shortcut)?; + let mut hotkey_state = state.lock(); + + if let Some(manager) = &hotkey_state.manager { + manager.register(hotkey.clone())?; + hotkey_state.registered_hotkey = Some(hotkey); + Ok(()) + } else { + Err("Hotkey manager not initialized".into()) + } +} + +fn parse_hotkey(shortcut: &[String]) -> Result> { + let mut modifiers = Modifiers::empty(); + let mut code = None; + + for part in shortcut { + match part.as_str() { + "ControlLeft" => modifiers |= Modifiers::CONTROL, + "AltLeft" => modifiers |= Modifiers::ALT, + "ShiftLeft" => modifiers |= Modifiers::SHIFT, + "MetaLeft" => modifiers |= Modifiers::META, + key => code = Some(Code::from(KeyCode::from_str(key)?)), + } + } + + let key_code = code.ok_or_else(|| "No valid key code found".to_string())?; + Ok(HotKey::new(Some(modifiers), key_code)) +} + +fn handle_hotkey_event(app_handle: &AppHandle) { + let window = app_handle.get_webview_window("main").unwrap(); + if window.is_visible().unwrap() { + window.hide().unwrap(); + } else { + window.set_always_on_top(true).unwrap(); + window.show().unwrap(); + window.set_focus().unwrap(); + + let window_clone = window.clone(); + std::thread::spawn(move || { + std::thread::sleep(std::time::Duration::from_millis(100)); + window_clone.set_always_on_top(false).unwrap(); + }); + + center_window_on_current_monitor(&window); + } + + let _ = app_handle.track_event( + "hotkey_triggered", + Some( + serde_json::json!({ + "action": if window.is_visible().unwrap() { "hide" } else { "show" } + }) + ) + ); } \ No newline at end of file diff --git a/src-tauri/src/api/mod.rs b/src-tauri/src/api/mod.rs index e3f7afa..bb12e15 100644 --- a/src-tauri/src/api/mod.rs +++ b/src-tauri/src/api/mod.rs @@ -1,4 +1,4 @@ -pub mod clipboard; -pub mod hotkeys; -pub mod tray; -pub mod updater; +pub mod clipboard; +pub mod hotkeys; +pub mod tray; +pub mod updater; diff --git a/src-tauri/src/api/tray.rs b/src-tauri/src/api/tray.rs index 2ae2bfa..6ad5c16 100644 --- a/src-tauri/src/api/tray.rs +++ b/src-tauri/src/api/tray.rs @@ -1,61 +1,61 @@ -use tauri::{ menu::{ MenuBuilder, MenuItemBuilder }, tray::TrayIconBuilder, Emitter, Manager }; -use tauri_plugin_aptabase::EventTracker; - -pub fn setup(app: &mut tauri::App) -> Result<(), Box> { - let window = app.get_webview_window("main").unwrap(); - let is_visible = window.is_visible().unwrap(); - let _ = app.track_event( - "tray_toggle", - Some(serde_json::json!({ - "action": if is_visible { "hide" } else { "show" } - })) - ); - - let icon_bytes = include_bytes!("../../icons/Square71x71Logo.png"); - let icon = tauri::image::Image::from_bytes(icon_bytes).unwrap(); - - let _tray = TrayIconBuilder::new() - .menu( - &MenuBuilder::new(app) - .items(&[&MenuItemBuilder::with_id("app_name", "Qopy").enabled(false).build(app)?]) - .items(&[&MenuItemBuilder::with_id("show", "Show/Hide").build(app)?]) - .items(&[&MenuItemBuilder::with_id("settings", "Settings").build(app)?]) - .items(&[&MenuItemBuilder::with_id("quit", "Quit").build(app)?]) - .build()? - ) - .on_menu_event(move |_app, event| { - match event.id().as_ref() { - "quit" => { - let _ = _app.track_event("app_quit", None); - std::process::exit(0); - } - "show" => { - let _ = _app.track_event( - "tray_toggle", - Some( - serde_json::json!({ - "action": if is_visible { "hide" } else { "show" } - }) - ) - ); - let is_visible = window.is_visible().unwrap(); - if is_visible { - window.hide().unwrap(); - } else { - window.show().unwrap(); - window.set_focus().unwrap(); - } - window.emit("main_route", ()).unwrap(); - } - "settings" => { - let _ = _app.track_event("tray_settings", None); - window.emit("settings", ()).unwrap(); - } - _ => (), - } - }) - .icon(icon) - .build(app)?; - - Ok(()) -} +use tauri::{ menu::{ MenuBuilder, MenuItemBuilder }, tray::TrayIconBuilder, Emitter, Manager }; +use tauri_plugin_aptabase::EventTracker; + +pub fn setup(app: &mut tauri::App) -> Result<(), Box> { + let window = app.get_webview_window("main").unwrap(); + let is_visible = window.is_visible().unwrap(); + let _ = app.track_event( + "tray_toggle", + Some(serde_json::json!({ + "action": if is_visible { "hide" } else { "show" } + })) + ); + + let icon_bytes = include_bytes!("../../icons/Square71x71Logo.png"); + let icon = tauri::image::Image::from_bytes(icon_bytes).unwrap(); + + let _tray = TrayIconBuilder::new() + .menu( + &MenuBuilder::new(app) + .items(&[&MenuItemBuilder::with_id("app_name", "Qopy").enabled(false).build(app)?]) + .items(&[&MenuItemBuilder::with_id("show", "Show/Hide").build(app)?]) + .items(&[&MenuItemBuilder::with_id("settings", "Settings").build(app)?]) + .items(&[&MenuItemBuilder::with_id("quit", "Quit").build(app)?]) + .build()? + ) + .on_menu_event(move |_app, event| { + match event.id().as_ref() { + "quit" => { + let _ = _app.track_event("app_quit", None); + std::process::exit(0); + } + "show" => { + let _ = _app.track_event( + "tray_toggle", + Some( + serde_json::json!({ + "action": if is_visible { "hide" } else { "show" } + }) + ) + ); + let is_visible = window.is_visible().unwrap(); + if is_visible { + window.hide().unwrap(); + } else { + window.show().unwrap(); + window.set_focus().unwrap(); + } + window.emit("main_route", ()).unwrap(); + } + "settings" => { + let _ = _app.track_event("tray_settings", None); + window.emit("settings", ()).unwrap(); + } + _ => (), + } + }) + .icon(icon) + .build(app)?; + + Ok(()) +} diff --git a/src-tauri/src/api/updater.rs b/src-tauri/src/api/updater.rs index da8737e..c08e0ed 100644 --- a/src-tauri/src/api/updater.rs +++ b/src-tauri/src/api/updater.rs @@ -1,94 +1,94 @@ -use tauri::{ async_runtime, AppHandle, Manager }; -use tauri_plugin_dialog::{ DialogExt, MessageDialogButtons, MessageDialogKind }; -use tauri_plugin_updater::UpdaterExt; - -pub async fn check_for_updates(app: AppHandle, prompted: bool) { - println!("Checking for updates..."); - - let updater = app.updater().unwrap(); - let response = updater.check().await; - - match response { - Ok(Some(update)) => { - let cur_ver = &update.current_version; - let new_ver = &update.version; - let mut msg = String::new(); - msg.extend([ - &format!("{cur_ver} -> {new_ver}\n\n"), - "Would you like to install it now?", - ]); - - let window = app.get_webview_window("main").unwrap(); - window.show().unwrap(); - window.set_focus().unwrap(); - - app.dialog() - .message(msg) - .title("Qopy Update Available") - .buttons( - MessageDialogButtons::OkCancelCustom( - String::from("Install"), - String::from("Cancel") - ) - ) - .show(move |response| { - if !response { - return; - } - async_runtime::spawn(async move { - match - update.download_and_install( - |_, _| {}, - || {} - ).await - { - Ok(_) => { - app.dialog() - .message( - "Update installed successfully. The application needs to restart to apply the changes." - ) - .title("Qopy Update Installed") - .buttons( - MessageDialogButtons::OkCancelCustom( - String::from("Restart"), - String::from("Cancel") - ) - ) - .show(move |response| { - if response { - app.restart(); - } - }); - } - Err(e) => { - println!("Error installing new update: {:?}", e); - app.dialog() - .message( - "Failed to install new update. The new update can be downloaded from Github" - ) - .kind(MessageDialogKind::Error) - .show(|_| {}); - } - } - }); - }); - } - Ok(None) => { - println!("No updates available."); - } - Err(e) => { - if prompted { - let window = app.get_webview_window("main").unwrap(); - window.show().unwrap(); - window.set_focus().unwrap(); - - app.dialog() - .message("No updates available.") - .title("Qopy Update Check") - .show(|_| {}); - } - - println!("No updates available. {}", e.to_string()); - } - } -} +use tauri::{ async_runtime, AppHandle, Manager }; +use tauri_plugin_dialog::{ DialogExt, MessageDialogButtons, MessageDialogKind }; +use tauri_plugin_updater::UpdaterExt; + +pub async fn check_for_updates(app: AppHandle, prompted: bool) { + println!("Checking for updates..."); + + let updater = app.updater().unwrap(); + let response = updater.check().await; + + match response { + Ok(Some(update)) => { + let cur_ver = &update.current_version; + let new_ver = &update.version; + let mut msg = String::new(); + msg.extend([ + &format!("{cur_ver} -> {new_ver}\n\n"), + "Would you like to install it now?", + ]); + + let window = app.get_webview_window("main").unwrap(); + window.show().unwrap(); + window.set_focus().unwrap(); + + app.dialog() + .message(msg) + .title("Qopy Update Available") + .buttons( + MessageDialogButtons::OkCancelCustom( + String::from("Install"), + String::from("Cancel") + ) + ) + .show(move |response| { + if !response { + return; + } + async_runtime::spawn(async move { + match + update.download_and_install( + |_, _| {}, + || {} + ).await + { + Ok(_) => { + app.dialog() + .message( + "Update installed successfully. The application needs to restart to apply the changes." + ) + .title("Qopy Update Installed") + .buttons( + MessageDialogButtons::OkCancelCustom( + String::from("Restart"), + String::from("Cancel") + ) + ) + .show(move |response| { + if response { + app.restart(); + } + }); + } + Err(e) => { + println!("Error installing new update: {:?}", e); + app.dialog() + .message( + "Failed to install new update. The new update can be downloaded from Github" + ) + .kind(MessageDialogKind::Error) + .show(|_| {}); + } + } + }); + }); + } + Ok(None) => { + println!("No updates available."); + } + Err(e) => { + if prompted { + let window = app.get_webview_window("main").unwrap(); + window.show().unwrap(); + window.set_focus().unwrap(); + + app.dialog() + .message("No updates available.") + .title("Qopy Update Check") + .show(|_| {}); + } + + println!("No updates available. {}", e.to_string()); + } + } +} diff --git a/src-tauri/src/db/database.rs b/src-tauri/src/db/database.rs index 264d308..30881d2 100644 --- a/src-tauri/src/db/database.rs +++ b/src-tauri/src/db/database.rs @@ -1,107 +1,107 @@ -use include_dir::{ include_dir, Dir }; -use sqlx::sqlite::{ SqlitePool, SqlitePoolOptions }; -use std::fs; -use tauri::Manager; -use tokio::runtime::Runtime as TokioRuntime; - -static MIGRATIONS_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/src/db/migrations"); - -pub fn setup(app: &mut tauri::App) -> Result<(), Box> { - let rt = TokioRuntime::new().expect("Failed to create Tokio runtime"); - app.manage(rt); - - let rt = app.state::(); - - let app_data_dir = app.path().app_data_dir().unwrap(); - fs::create_dir_all(&app_data_dir).expect("Failed to create app data directory"); - - let db_path = app_data_dir.join("data.db"); - let is_new_db = !db_path.exists(); - if is_new_db { - fs::File::create(&db_path).expect("Failed to create database file"); - } - - let db_url = format!("sqlite:{}", db_path.to_str().unwrap()); - let pool = rt.block_on(async { - SqlitePoolOptions::new() - .max_connections(5) - .connect(&db_url).await - .expect("Failed to create pool") - }); - - app.manage(pool.clone()); - - rt.block_on(async { - apply_migrations(&pool).await?; - if is_new_db { - if let Err(e) = super::history::initialize_history(&pool).await { - eprintln!("Failed to initialize history: {}", e); - } - if let Err(e) = super::settings::initialize_settings(&pool).await { - eprintln!("Failed to initialize settings: {}", e); - } - } - Ok::<(), Box>(()) - })?; - - Ok(()) -} - -async fn apply_migrations(pool: &SqlitePool) -> Result<(), Box> { - sqlx - ::query( - "CREATE TABLE IF NOT EXISTS schema_version ( - version INTEGER PRIMARY KEY, - applied_at DATETIME DEFAULT CURRENT_TIMESTAMP - );" - ) - .execute(pool).await?; - - let current_version: Option = sqlx - ::query_scalar("SELECT MAX(version) FROM schema_version") - .fetch_one(pool).await?; - - let current_version = current_version.unwrap_or(0); - - let mut migration_files: Vec<(i64, &str)> = MIGRATIONS_DIR.files() - .filter_map(|file| { - let file_name = file.path().file_name()?.to_str()?; - if file_name.ends_with(".sql") && file_name.starts_with("v") { - let version: i64 = file_name - .trim_start_matches("v") - .trim_end_matches(".sql") - .parse() - .ok()?; - Some((version, file.contents_utf8()?)) - } else { - None - } - }) - .collect(); - - migration_files.sort_by_key(|(version, _)| *version); - - for (version, content) in migration_files { - if version > current_version { - let statements: Vec<&str> = content - .split(';') - .map(|s| s.trim()) - .filter(|s| !s.is_empty()) - .collect(); - - for statement in statements { - sqlx - ::query(statement) - .execute(pool).await - .map_err(|e| format!("Failed to execute migration {}: {}", version, e))?; - } - - sqlx - ::query("INSERT INTO schema_version (version) VALUES (?)") - .bind(version) - .execute(pool).await?; - } - } - - Ok(()) -} +use include_dir::{ include_dir, Dir }; +use sqlx::sqlite::{ SqlitePool, SqlitePoolOptions }; +use std::fs; +use tauri::Manager; +use tokio::runtime::Runtime as TokioRuntime; + +static MIGRATIONS_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/src/db/migrations"); + +pub fn setup(app: &mut tauri::App) -> Result<(), Box> { + let rt = TokioRuntime::new().expect("Failed to create Tokio runtime"); + app.manage(rt); + + let rt = app.state::(); + + let app_data_dir = app.path().app_data_dir().unwrap(); + fs::create_dir_all(&app_data_dir).expect("Failed to create app data directory"); + + let db_path = app_data_dir.join("data.db"); + let is_new_db = !db_path.exists(); + if is_new_db { + fs::File::create(&db_path).expect("Failed to create database file"); + } + + let db_url = format!("sqlite:{}", db_path.to_str().unwrap()); + let pool = rt.block_on(async { + SqlitePoolOptions::new() + .max_connections(5) + .connect(&db_url).await + .expect("Failed to create pool") + }); + + app.manage(pool.clone()); + + rt.block_on(async { + apply_migrations(&pool).await?; + if is_new_db { + if let Err(e) = super::history::initialize_history(&pool).await { + eprintln!("Failed to initialize history: {}", e); + } + if let Err(e) = super::settings::initialize_settings(&pool).await { + eprintln!("Failed to initialize settings: {}", e); + } + } + Ok::<(), Box>(()) + })?; + + Ok(()) +} + +async fn apply_migrations(pool: &SqlitePool) -> Result<(), Box> { + sqlx + ::query( + "CREATE TABLE IF NOT EXISTS schema_version ( + version INTEGER PRIMARY KEY, + applied_at DATETIME DEFAULT CURRENT_TIMESTAMP + );" + ) + .execute(pool).await?; + + let current_version: Option = sqlx + ::query_scalar("SELECT MAX(version) FROM schema_version") + .fetch_one(pool).await?; + + let current_version = current_version.unwrap_or(0); + + let mut migration_files: Vec<(i64, &str)> = MIGRATIONS_DIR.files() + .filter_map(|file| { + let file_name = file.path().file_name()?.to_str()?; + if file_name.ends_with(".sql") && file_name.starts_with("v") { + let version: i64 = file_name + .trim_start_matches("v") + .trim_end_matches(".sql") + .parse() + .ok()?; + Some((version, file.contents_utf8()?)) + } else { + None + } + }) + .collect(); + + migration_files.sort_by_key(|(version, _)| *version); + + for (version, content) in migration_files { + if version > current_version { + let statements: Vec<&str> = content + .split(';') + .map(|s| s.trim()) + .filter(|s| !s.is_empty()) + .collect(); + + for statement in statements { + sqlx + ::query(statement) + .execute(pool).await + .map_err(|e| format!("Failed to execute migration {}: {}", version, e))?; + } + + sqlx + ::query("INSERT INTO schema_version (version) VALUES (?)") + .bind(version) + .execute(pool).await?; + } + } + + Ok(()) +} diff --git a/src-tauri/src/db/history.rs b/src-tauri/src/db/history.rs index 4f70310..24a7b59 100644 --- a/src-tauri/src/db/history.rs +++ b/src-tauri/src/db/history.rs @@ -1,217 +1,226 @@ -use crate::utils::types::{ ContentType, HistoryItem }; -use base64::{ engine::general_purpose::STANDARD, Engine }; -use rand::{ rng, Rng }; -use rand::distr::Alphanumeric; -use sqlx::{ Row, SqlitePool }; -use std::fs; -use tauri_plugin_aptabase::EventTracker; - -pub async fn initialize_history(pool: &SqlitePool) -> Result<(), Box> { - let id: String = rng() - .sample_iter(&Alphanumeric) - .take(16) - .map(char::from) - .collect(); - - sqlx::query( - "INSERT INTO history (id, source, content_type, content, timestamp) VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)" - ) - .bind(id) - .bind("System") - .bind("text") - .bind("Welcome to your clipboard history!") - .execute(pool).await?; - - Ok(()) -} - -#[tauri::command] -pub async fn get_history(pool: tauri::State<'_, SqlitePool>) -> Result, String> { - let rows = sqlx - ::query( - "SELECT id, source, source_icon, content_type, content, favicon, timestamp, language FROM history ORDER BY timestamp DESC" - ) - .fetch_all(&*pool).await - .map_err(|e| e.to_string())?; - - let items = rows - .iter() - .map(|row| HistoryItem { - id: row.get("id"), - source: row.get("source"), - source_icon: row.get("source_icon"), - content_type: ContentType::from(row.get::("content_type")), - content: row.get("content"), - favicon: row.get("favicon"), - timestamp: row.get("timestamp"), - language: row.get("language"), - }) - .collect(); - - Ok(items) -} - -#[tauri::command] -pub async fn add_history_item( - app_handle: tauri::AppHandle, - pool: tauri::State<'_, SqlitePool>, - item: HistoryItem -) -> Result<(), String> { - let (id, source, source_icon, content_type, content, favicon, timestamp, language) = - item.to_row(); - - let existing = sqlx - ::query("SELECT id FROM history WHERE content = ? AND content_type = ?") - .bind(&content) - .bind(&content_type) - .fetch_optional(&*pool).await - .map_err(|e| e.to_string())?; - - match existing { - Some(_) => { - sqlx - ::query( - "UPDATE history SET timestamp = strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now') WHERE content = ? AND content_type = ?" - ) - .bind(&content) - .bind(&content_type) - .execute(&*pool).await - .map_err(|e| e.to_string())?; - } - None => { - sqlx - ::query( - "INSERT INTO history (id, source, source_icon, content_type, content, favicon, timestamp, language) VALUES (?, ?, ?, ?, ?, ?, ?, ?)" - ) - .bind(id) - .bind(source) - .bind(source_icon) - .bind(content_type) - .bind(content) - .bind(favicon) - .bind(timestamp) - .bind(language) - .execute(&*pool).await - .map_err(|e| e.to_string())?; - } - } - - let _ = app_handle.track_event( - "history_item_added", - Some(serde_json::json!({ - "content_type": item.content_type.to_string() - })) - ); - - Ok(()) -} - -#[tauri::command] -pub async fn search_history( - pool: tauri::State<'_, SqlitePool>, - query: String -) -> Result, String> { - if query.trim().is_empty() { - return Ok(Vec::new()); - } - - let query = format!("%{}%", query); - - let rows = sqlx - ::query( - "SELECT id, source, source_icon, content_type, content, favicon, timestamp, language - FROM history - WHERE content LIKE ? - ORDER BY timestamp DESC - LIMIT 100" - ) - .bind(query) - .fetch_all(&*pool).await - .map_err(|e| e.to_string())?; - - let mut items = Vec::with_capacity(rows.len()); - for row in rows.iter() { - items.push(HistoryItem { - id: row.get("id"), - source: row.get("source"), - source_icon: row.get("source_icon"), - content_type: ContentType::from(row.get::("content_type")), - content: row.get("content"), - favicon: row.get("favicon"), - timestamp: row.get("timestamp"), - language: row.get("language"), - }); - } - - Ok(items) -} - -#[tauri::command] -pub async fn load_history_chunk( - pool: tauri::State<'_, SqlitePool>, - offset: i64, - limit: i64 -) -> Result, String> { - let rows = sqlx - ::query( - "SELECT id, source, source_icon, content_type, content, favicon, timestamp, language FROM history ORDER BY timestamp DESC LIMIT ? OFFSET ?" - ) - .bind(limit) - .bind(offset) - .fetch_all(&*pool).await - .map_err(|e| e.to_string())?; - - let items = rows - .iter() - .map(|row| HistoryItem { - id: row.get("id"), - source: row.get("source"), - source_icon: row.get("source_icon"), - content_type: ContentType::from(row.get::("content_type")), - content: row.get("content"), - favicon: row.get("favicon"), - timestamp: row.get("timestamp"), - language: row.get("language"), - }) - .collect(); - - Ok(items) -} - -#[tauri::command] -pub async fn delete_history_item( - app_handle: tauri::AppHandle, - pool: tauri::State<'_, SqlitePool>, - id: String -) -> Result<(), String> { - sqlx - ::query("DELETE FROM history WHERE id = ?") - .bind(id) - .execute(&*pool).await - .map_err(|e| e.to_string())?; - - let _ = app_handle.track_event("history_item_deleted", None); - - Ok(()) -} - -#[tauri::command] -pub async fn clear_history( - app_handle: tauri::AppHandle, - pool: tauri::State<'_, SqlitePool> -) -> Result<(), String> { - sqlx - ::query("DELETE FROM history") - .execute(&*pool).await - .map_err(|e| e.to_string())?; - - let _ = app_handle.track_event("history_cleared", None); - - Ok(()) -} - -#[tauri::command] -pub async fn read_image(filename: String) -> Result { - let bytes = fs::read(filename).map_err(|e| e.to_string())?; - Ok(STANDARD.encode(bytes)) -} +use crate::utils::types::{ ContentType, HistoryItem }; +use base64::{ engine::general_purpose::STANDARD, Engine }; +use rand::{ rng, Rng }; +use rand::distr::Alphanumeric; +use sqlx::{ Row, SqlitePool }; +use std::fs; +use tauri_plugin_aptabase::EventTracker; +use tauri::Emitter; + +pub async fn initialize_history(pool: &SqlitePool) -> Result<(), Box> { + let id: String = rng() + .sample_iter(&Alphanumeric) + .take(16) + .map(char::from) + .collect(); + + sqlx::query( + "INSERT INTO history (id, source, content_type, content, timestamp) VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)" + ) + .bind(id) + .bind("System") + .bind("text") + .bind("Welcome to your clipboard history!") + .execute(pool).await?; + + Ok(()) +} + +#[tauri::command] +pub async fn get_history(pool: tauri::State<'_, SqlitePool>) -> Result, String> { + let rows = sqlx + ::query( + "SELECT id, source, source_icon, content_type, content, favicon, timestamp, language FROM history ORDER BY timestamp DESC" + ) + .fetch_all(&*pool).await + .map_err(|e| e.to_string())?; + + let items = rows + .iter() + .map(|row| HistoryItem { + id: row.get("id"), + source: row.get("source"), + source_icon: row.get("source_icon"), + content_type: ContentType::from(row.get::("content_type")), + content: row.get("content"), + favicon: row.get("favicon"), + timestamp: row.get("timestamp"), + language: row.get("language"), + }) + .collect(); + + Ok(items) +} + +#[tauri::command] +pub async fn add_history_item( + app_handle: tauri::AppHandle, + pool: tauri::State<'_, SqlitePool>, + item: HistoryItem +) -> Result<(), String> { + let (id, source, source_icon, content_type, content, favicon, timestamp, language) = + item.to_row(); + + let existing = sqlx + ::query("SELECT id FROM history WHERE content = ? AND content_type = ?") + .bind(&content) + .bind(&content_type) + .fetch_optional(&*pool).await + .map_err(|e| e.to_string())?; + + match existing { + Some(_) => { + sqlx + ::query( + "UPDATE history SET source = ?, source_icon = ?, timestamp = strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now'), favicon = ?, language = ? WHERE content = ? AND content_type = ?" + ) + .bind(&source) + .bind(&source_icon) + .bind(&favicon) + .bind(&language) + .bind(&content) + .bind(&content_type) + .execute(&*pool).await + .map_err(|e| e.to_string())?; + } + None => { + sqlx + ::query( + "INSERT INTO history (id, source, source_icon, content_type, content, favicon, timestamp, language) VALUES (?, ?, ?, ?, ?, ?, ?, ?)" + ) + .bind(id) + .bind(source) + .bind(source_icon) + .bind(content_type) + .bind(content) + .bind(favicon) + .bind(timestamp) + .bind(language) + .execute(&*pool).await + .map_err(|e| e.to_string())?; + } + } + + let _ = app_handle.track_event( + "history_item_added", + Some(serde_json::json!({ + "content_type": item.content_type.to_string() + })) + ); + + let _ = app_handle.emit("clipboard-content-updated", ()); + + Ok(()) +} + +#[tauri::command] +pub async fn search_history( + pool: tauri::State<'_, SqlitePool>, + query: String +) -> Result, String> { + if query.trim().is_empty() { + return Ok(Vec::new()); + } + + let query = format!("%{}%", query); + + let rows = sqlx + ::query( + "SELECT id, source, source_icon, content_type, content, favicon, timestamp, language + FROM history + WHERE content LIKE ? + ORDER BY timestamp DESC + LIMIT 100" + ) + .bind(query) + .fetch_all(&*pool).await + .map_err(|e| e.to_string())?; + + let mut items = Vec::with_capacity(rows.len()); + for row in rows.iter() { + items.push(HistoryItem { + id: row.get("id"), + source: row.get("source"), + source_icon: row.get("source_icon"), + content_type: ContentType::from(row.get::("content_type")), + content: row.get("content"), + favicon: row.get("favicon"), + timestamp: row.get("timestamp"), + language: row.get("language"), + }); + } + + Ok(items) +} + +#[tauri::command] +pub async fn load_history_chunk( + pool: tauri::State<'_, SqlitePool>, + offset: i64, + limit: i64 +) -> Result, String> { + let rows = sqlx + ::query( + "SELECT id, source, source_icon, content_type, content, favicon, timestamp, language FROM history ORDER BY timestamp DESC LIMIT ? OFFSET ?" + ) + .bind(limit) + .bind(offset) + .fetch_all(&*pool).await + .map_err(|e| e.to_string())?; + + let items = rows + .iter() + .map(|row| HistoryItem { + id: row.get("id"), + source: row.get("source"), + source_icon: row.get("source_icon"), + content_type: ContentType::from(row.get::("content_type")), + content: row.get("content"), + favicon: row.get("favicon"), + timestamp: row.get("timestamp"), + language: row.get("language"), + }) + .collect(); + + Ok(items) +} + +#[tauri::command] +pub async fn delete_history_item( + app_handle: tauri::AppHandle, + pool: tauri::State<'_, SqlitePool>, + id: String +) -> Result<(), String> { + sqlx + ::query("DELETE FROM history WHERE id = ?") + .bind(id) + .execute(&*pool).await + .map_err(|e| e.to_string())?; + + let _ = app_handle.track_event("history_item_deleted", None); + let _ = app_handle.emit("clipboard-content-updated", ()); + + Ok(()) +} + +#[tauri::command] +pub async fn clear_history( + app_handle: tauri::AppHandle, + pool: tauri::State<'_, SqlitePool> +) -> Result<(), String> { + sqlx + ::query("DELETE FROM history") + .execute(&*pool).await + .map_err(|e| e.to_string())?; + + let _ = app_handle.track_event("history_cleared", None); + let _ = app_handle.emit("clipboard-content-updated", ()); + + Ok(()) +} + +#[tauri::command] +pub async fn read_image(filename: String) -> Result { + let bytes = fs::read(filename).map_err(|e| e.to_string())?; + Ok(STANDARD.encode(bytes)) +} diff --git a/src-tauri/src/db/migrations/v1.sql b/src-tauri/src/db/migrations/v1.sql index e2028ae..95878c8 100644 --- a/src-tauri/src/db/migrations/v1.sql +++ b/src-tauri/src/db/migrations/v1.sql @@ -1,12 +1,12 @@ -CREATE TABLE IF NOT EXISTS settings ( - key TEXT PRIMARY KEY, - value TEXT NOT NULL -); - -CREATE TABLE IF NOT EXISTS history ( - id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))), - content_type TEXT NOT NULL, - content TEXT NOT NULL, - favicon TEXT, - timestamp DATETIME DEFAULT CURRENT_TIMESTAMP +CREATE TABLE IF NOT EXISTS settings ( + key TEXT PRIMARY KEY, + value TEXT NOT NULL +); + +CREATE TABLE IF NOT EXISTS history ( + id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))), + content_type TEXT NOT NULL, + content TEXT NOT NULL, + favicon TEXT, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP ); \ No newline at end of file diff --git a/src-tauri/src/db/migrations/v2.sql b/src-tauri/src/db/migrations/v2.sql index 312c5ef..5cc1620 100644 --- a/src-tauri/src/db/migrations/v2.sql +++ b/src-tauri/src/db/migrations/v2.sql @@ -1,3 +1,3 @@ -ALTER TABLE history ADD COLUMN source TEXT DEFAULT 'System' NOT NULL; -ALTER TABLE history ADD COLUMN source_icon TEXT; -ALTER TABLE history ADD COLUMN language TEXT; +ALTER TABLE history ADD COLUMN source TEXT DEFAULT 'System' NOT NULL; +ALTER TABLE history ADD COLUMN source_icon TEXT; +ALTER TABLE history ADD COLUMN language TEXT; diff --git a/src-tauri/src/db/migrations/v3.sql b/src-tauri/src/db/migrations/v3.sql index e299cae..684deb7 100644 --- a/src-tauri/src/db/migrations/v3.sql +++ b/src-tauri/src/db/migrations/v3.sql @@ -1 +1 @@ -INSERT INTO settings (key, value) VALUES ('autostart', 'true'); +INSERT INTO settings (key, value) VALUES ('autostart', 'true'); diff --git a/src-tauri/src/db/mod.rs b/src-tauri/src/db/mod.rs index 8c147c6..d80ce09 100644 --- a/src-tauri/src/db/mod.rs +++ b/src-tauri/src/db/mod.rs @@ -1,3 +1,3 @@ -pub mod database; -pub mod history; -pub mod settings; +pub mod database; +pub mod history; +pub mod settings; diff --git a/src-tauri/src/db/settings.rs b/src-tauri/src/db/settings.rs index 2539ab7..20fd54a 100644 --- a/src-tauri/src/db/settings.rs +++ b/src-tauri/src/db/settings.rs @@ -1,87 +1,87 @@ -use serde::{ Deserialize, Serialize }; -use serde_json; -use sqlx::Row; -use sqlx::SqlitePool; -use tauri::{ Emitter, Manager }; -use tauri_plugin_aptabase::EventTracker; - -#[derive(Deserialize, Serialize)] -struct KeybindSetting { - keybind: Vec, -} - -pub async fn initialize_settings(pool: &SqlitePool) -> Result<(), Box> { - let default_keybind = KeybindSetting { - keybind: vec!["Meta".to_string(), "V".to_string()], - }; - let json = serde_json::to_string(&default_keybind)?; - - sqlx - ::query("INSERT INTO settings (key, value) VALUES ('keybind', ?)") - .bind(json) - .execute(pool).await?; - - Ok(()) -} - -#[tauri::command] -pub async fn get_setting( - pool: tauri::State<'_, SqlitePool>, - key: String -) -> Result { - let row = sqlx - ::query("SELECT value FROM settings WHERE key = ?") - .bind(key) - .fetch_optional(&*pool).await - .map_err(|e| e.to_string())?; - - Ok(row.map(|r| r.get("value")).unwrap_or_default()) -} - -#[tauri::command] -pub async fn save_setting( - app_handle: tauri::AppHandle, - pool: tauri::State<'_, SqlitePool>, - key: String, - value: String -) -> Result<(), String> { - sqlx - ::query("INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)") - .bind(key.clone()) - .bind(value.clone()) - .execute(&*pool).await - .map_err(|e| e.to_string())?; - - let _ = app_handle.track_event( - "setting_saved", - Some(serde_json::json!({ - "key": key - })) - ); - - if key == "keybind" { - let _ = app_handle.emit("update-shortcut", &value).map_err(|e| e.to_string())?; - } - - Ok(()) -} - -#[tauri::command] -pub async fn get_keybind(app_handle: tauri::AppHandle) -> Result, String> { - let pool = app_handle.state::(); - - let row = sqlx - ::query("SELECT value FROM settings WHERE key = 'keybind'") - .fetch_optional(&*pool).await - .map_err(|e| e.to_string())?; - - let json = row - .map(|r| r.get::("value")) - .unwrap_or_else(|| { - serde_json - ::to_string(&vec!["MetaLeft".to_string(), "KeyV".to_string()]) - .expect("Failed to serialize default keybind") - }); - - serde_json::from_str::>(&json).map_err(|e| e.to_string()) -} +use serde::{ Deserialize, Serialize }; +use serde_json; +use sqlx::Row; +use sqlx::SqlitePool; +use tauri::{ Emitter, Manager }; +use tauri_plugin_aptabase::EventTracker; + +#[derive(Deserialize, Serialize)] +struct KeybindSetting { + keybind: Vec, +} + +pub async fn initialize_settings(pool: &SqlitePool) -> Result<(), Box> { + let default_keybind = KeybindSetting { + keybind: vec!["Meta".to_string(), "V".to_string()], + }; + let json = serde_json::to_string(&default_keybind)?; + + sqlx + ::query("INSERT INTO settings (key, value) VALUES ('keybind', ?)") + .bind(json) + .execute(pool).await?; + + Ok(()) +} + +#[tauri::command] +pub async fn get_setting( + pool: tauri::State<'_, SqlitePool>, + key: String +) -> Result { + let row = sqlx + ::query("SELECT value FROM settings WHERE key = ?") + .bind(key) + .fetch_optional(&*pool).await + .map_err(|e| e.to_string())?; + + Ok(row.map(|r| r.get("value")).unwrap_or_default()) +} + +#[tauri::command] +pub async fn save_setting( + app_handle: tauri::AppHandle, + pool: tauri::State<'_, SqlitePool>, + key: String, + value: String +) -> Result<(), String> { + sqlx + ::query("INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)") + .bind(key.clone()) + .bind(value.clone()) + .execute(&*pool).await + .map_err(|e| e.to_string())?; + + let _ = app_handle.track_event( + "setting_saved", + Some(serde_json::json!({ + "key": key + })) + ); + + if key == "keybind" { + let _ = app_handle.emit("update-shortcut", &value).map_err(|e| e.to_string())?; + } + + Ok(()) +} + +#[tauri::command] +pub async fn get_keybind(app_handle: tauri::AppHandle) -> Result, String> { + let pool = app_handle.state::(); + + let row = sqlx + ::query("SELECT value FROM settings WHERE key = 'keybind'") + .fetch_optional(&*pool).await + .map_err(|e| e.to_string())?; + + let json = row + .map(|r| r.get::("value")) + .unwrap_or_else(|| { + serde_json + ::to_string(&vec!["MetaLeft".to_string(), "KeyV".to_string()]) + .expect("Failed to serialize default keybind") + }); + + serde_json::from_str::>(&json).map_err(|e| e.to_string()) +} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 3629212..64b8b68 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,135 +1,136 @@ -#![cfg_attr(all(not(debug_assertions), target_os = "windows"), windows_subsystem = "windows")] - -mod api; -mod db; -mod utils; - -use sqlx::sqlite::SqlitePoolOptions; -use std::fs; -use tauri::Manager; -use tauri_plugin_aptabase::{ EventTracker, InitOptions }; -use tauri_plugin_autostart::MacosLauncher; -use tauri_plugin_prevent_default::Flags; - -fn main() { - let runtime = tokio::runtime::Runtime::new().expect("Failed to create Tokio runtime"); - let _guard = runtime.enter(); - - tauri::Builder - ::default() - .plugin(tauri_plugin_clipboard::init()) - .plugin(tauri_plugin_os::init()) - .plugin(tauri_plugin_sql::Builder::default().build()) - .plugin(tauri_plugin_dialog::init()) - .plugin(tauri_plugin_fs::init()) - .plugin(tauri_plugin_updater::Builder::default().build()) - .plugin( - tauri_plugin_aptabase::Builder - ::new("A-SH-8937252746") - .with_options(InitOptions { - host: Some("https://aptabase.pandadev.net".to_string()), - flush_interval: None, - }) - .with_panic_hook( - Box::new(|client, info, msg| { - let location = info - .location() - .map(|loc| format!("{}:{}:{}", loc.file(), loc.line(), loc.column())) - .unwrap_or_else(|| "".to_string()); - - let _ = client.track_event( - "panic", - Some( - serde_json::json!({ - "info": format!("{} ({})", msg, location), - }) - ) - ); - }) - ) - .build() - ) - .plugin(tauri_plugin_autostart::init(MacosLauncher::LaunchAgent, Some(vec![]))) - .plugin( - tauri_plugin_prevent_default::Builder - ::new() - .with_flags(Flags::all().difference(Flags::CONTEXT_MENU)) - .build() - ) - .setup(|app| { - #[cfg(target_os = "macos")] - app.set_activation_policy(tauri::ActivationPolicy::Accessory); - - let app_data_dir = app.path().app_data_dir().unwrap(); - utils::logger::init_logger(&app_data_dir).expect("Failed to initialize logger"); - - fs::create_dir_all(&app_data_dir).expect("Failed to create app data directory"); - - let db_path = app_data_dir.join("data.db"); - let is_new_db = !db_path.exists(); - if is_new_db { - fs::File::create(&db_path).expect("Failed to create database file"); - } - - let db_url = format!("sqlite:{}", db_path.to_str().unwrap()); - - let app_handle = app.handle().clone(); - - let app_handle_clone = app_handle.clone(); - tauri::async_runtime::spawn(async move { - let pool = SqlitePoolOptions::new() - .max_connections(5) - .connect(&db_url).await - .expect("Failed to create pool"); - - app_handle_clone.manage(pool); - }); - - let main_window = app.get_webview_window("main"); - - let _ = db::database::setup(app); - api::hotkeys::setup(app_handle.clone()); - api::tray::setup(app)?; - api::clipboard::setup(app.handle()); - let _ = api::clipboard::start_monitor(app_handle.clone()); - - utils::commands::center_window_on_current_monitor(main_window.as_ref().unwrap()); - main_window - .as_ref() - .map(|w| w.hide()) - .unwrap_or(Ok(()))?; - - let _ = app.track_event("app_started", None); - - tauri::async_runtime::spawn(async move { - api::updater::check_for_updates(app_handle, false).await; - }); - - Ok(()) - }) - .on_window_event(|_app, _event| { - #[cfg(not(dev))] - if let tauri::WindowEvent::Focused(false) = _event { - if let Some(window) = _app.get_webview_window("main") { - let _ = window.hide(); - } - } - }) - .invoke_handler( - tauri::generate_handler![ - api::clipboard::write_and_paste, - db::history::get_history, - db::history::add_history_item, - db::history::search_history, - db::history::load_history_chunk, - db::history::delete_history_item, - db::history::clear_history, - db::history::read_image, - db::settings::get_setting, - db::settings::save_setting, - utils::commands::fetch_page_meta - ] - ) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); +#![cfg_attr(all(not(debug_assertions), target_os = "windows"), windows_subsystem = "windows")] + +mod api; +mod db; +mod utils; + +use sqlx::sqlite::SqlitePoolOptions; +use std::fs; +use tauri::Manager; +use tauri_plugin_aptabase::{ EventTracker, InitOptions }; +use tauri_plugin_autostart::MacosLauncher; +use tauri_plugin_prevent_default::Flags; + +fn main() { + let runtime = tokio::runtime::Runtime::new().expect("Failed to create Tokio runtime"); + let _guard = runtime.enter(); + + tauri::Builder + ::default() + .plugin(tauri_plugin_clipboard::init()) + .plugin(tauri_plugin_os::init()) + .plugin(tauri_plugin_sql::Builder::default().build()) + .plugin(tauri_plugin_dialog::init()) + .plugin(tauri_plugin_fs::init()) + .plugin(tauri_plugin_updater::Builder::default().build()) + .plugin( + tauri_plugin_aptabase::Builder + ::new("A-SH-8937252746") + .with_options(InitOptions { + host: Some("https://aptabase.pandadev.net".to_string()), + flush_interval: None, + }) + .with_panic_hook( + Box::new(|client, info, msg| { + let location = info + .location() + .map(|loc| format!("{}:{}:{}", loc.file(), loc.line(), loc.column())) + .unwrap_or_else(|| "".to_string()); + + let _ = client.track_event( + "panic", + Some( + serde_json::json!({ + "info": format!("{} ({})", msg, location), + }) + ) + ); + }) + ) + .build() + ) + .plugin(tauri_plugin_autostart::init(MacosLauncher::LaunchAgent, Some(vec![]))) + .plugin( + tauri_plugin_prevent_default::Builder + ::new() + .with_flags(Flags::all().difference(Flags::CONTEXT_MENU)) + .build() + ) + .setup(|app| { + #[cfg(target_os = "macos")] + app.set_activation_policy(tauri::ActivationPolicy::Accessory); + + let app_data_dir = app.path().app_data_dir().unwrap(); + utils::logger::init_logger(&app_data_dir).expect("Failed to initialize logger"); + + fs::create_dir_all(&app_data_dir).expect("Failed to create app data directory"); + + let db_path = app_data_dir.join("data.db"); + let is_new_db = !db_path.exists(); + if is_new_db { + fs::File::create(&db_path).expect("Failed to create database file"); + } + + let db_url = format!("sqlite:{}", db_path.to_str().unwrap()); + + let app_handle = app.handle().clone(); + + let app_handle_clone = app_handle.clone(); + tauri::async_runtime::spawn(async move { + let pool = SqlitePoolOptions::new() + .max_connections(5) + .connect(&db_url).await + .expect("Failed to create pool"); + + app_handle_clone.manage(pool); + }); + + let main_window = app.get_webview_window("main"); + + let _ = db::database::setup(app); + api::hotkeys::setup(app_handle.clone()); + api::tray::setup(app)?; + api::clipboard::setup(app.handle()); + let _ = api::clipboard::start_monitor(app_handle.clone()); + + utils::commands::center_window_on_current_monitor(main_window.as_ref().unwrap()); + main_window + .as_ref() + .map(|w| w.hide()) + .unwrap_or(Ok(()))?; + + let _ = app.track_event("app_started", None); + + tauri::async_runtime::spawn(async move { + api::updater::check_for_updates(app_handle, false).await; + }); + + Ok(()) + }) + .on_window_event(|_app, _event| { + #[cfg(not(dev))] + if let tauri::WindowEvent::Focused(false) = _event { + if let Some(window) = _app.get_webview_window("main") { + let _ = window.hide(); + } + } + }) + .invoke_handler( + tauri::generate_handler![ + api::clipboard::write_and_paste, + db::history::get_history, + db::history::add_history_item, + db::history::search_history, + db::history::load_history_chunk, + db::history::delete_history_item, + db::history::clear_history, + db::history::read_image, + db::settings::get_setting, + db::settings::save_setting, + utils::commands::fetch_page_meta, + utils::commands::get_app_info + ] + ) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); } \ No newline at end of file diff --git a/src-tauri/src/utils/commands.rs b/src-tauri/src/utils/commands.rs index ebf71b1..e1e4152 100644 --- a/src-tauri/src/utils/commands.rs +++ b/src-tauri/src/utils/commands.rs @@ -1,137 +1,155 @@ -use applications::{AppInfoContext, AppInfo, AppTrait, utils::image::RustImage}; -use base64::{ engine::general_purpose::STANDARD, Engine }; -use image::codecs::png::PngEncoder; -use tauri::PhysicalPosition; -use meta_fetcher; - -pub fn center_window_on_current_monitor(window: &tauri::WebviewWindow) { - if - let Some(monitor) = window - .available_monitors() - .unwrap() - .iter() - .find(|m| { - let primary_monitor = window - .primary_monitor() - .unwrap() - .expect("Failed to get primary monitor"); - let mouse_position = primary_monitor.position(); - let monitor_position = m.position(); - let monitor_size = m.size(); - mouse_position.x >= monitor_position.x && - mouse_position.x < monitor_position.x + (monitor_size.width as i32) && - mouse_position.y >= monitor_position.y && - mouse_position.y < monitor_position.y + (monitor_size.height as i32) - }) - { - let monitor_size = monitor.size(); - let window_size = window.outer_size().unwrap(); - - let x = ((monitor_size.width as i32) - (window_size.width as i32)) / 2; - let y = ((monitor_size.height as i32) - (window_size.height as i32)) / 2; - - window - .set_position(PhysicalPosition::new(monitor.position().x + x, monitor.position().y + y)) - .unwrap(); - } -} - -pub fn get_app_info() -> (String, Option) { - println!("Getting app info"); - let mut ctx = AppInfoContext::new(vec![]); - println!("Created AppInfoContext"); - ctx.refresh_apps().unwrap(); - println!("Refreshed apps"); - match ctx.get_frontmost_application() { - Ok(window) => { - println!("Found frontmost application: {}", window.name); - let name = window.name.clone(); - let icon = window - .load_icon() - .ok() - .map(|i| { - println!("Loading icon for {}", name); - let png = i.to_png().unwrap(); - let encoded = STANDARD.encode(png.get_bytes()); - println!("Icon encoded successfully"); - encoded - }); - println!("Returning app info: {} with icon: {}", name, icon.is_some()); - (name, icon) - } - Err(e) => { - println!("Failed to get frontmost application: {:?}", e); - ("System".to_string(), None) - } - } -} - -fn _process_icon_to_base64(path: &str) -> Result> { - let img = image::open(path)?; - let resized = img.resize(128, 128, image::imageops::FilterType::Lanczos3); - let mut png_buffer = Vec::new(); - resized.write_with_encoder(PngEncoder::new(&mut png_buffer))?; - Ok(STANDARD.encode(png_buffer)) -} - -pub fn detect_color(color: &str) -> bool { - let color = color.trim().to_lowercase(); - - // hex - if color.starts_with('#') && color.len() == color.trim_end_matches(char::is_whitespace).len() { - let hex = &color[1..]; - return match hex.len() { - 3 | 6 | 8 => hex.chars().all(|c| c.is_ascii_hexdigit()), - _ => false, - }; - } - - // rgb/rgba - if - (color.starts_with("rgb(") || color.starts_with("rgba(")) && - color.ends_with(")") && - !color[..color.len() - 1].contains(")") - { - let values = color - .trim_start_matches("rgba(") - .trim_start_matches("rgb(") - .trim_end_matches(')') - .split(',') - .collect::>(); - - return match values.len() { - 3 | 4 => values.iter().all(|v| v.trim().parse::().is_ok()), - _ => false, - }; - } - - // hsl/hsla - if - (color.starts_with("hsl(") || color.starts_with("hsla(")) && - color.ends_with(")") && - !color[..color.len() - 1].contains(")") - { - let values = color - .trim_start_matches("hsla(") - .trim_start_matches("hsl(") - .trim_end_matches(')') - .split(',') - .collect::>(); - - return match values.len() { - 3 | 4 => values.iter().all(|v| v.trim().parse::().is_ok()), - _ => false, - }; - } - - false -} - -#[tauri::command] -pub async fn fetch_page_meta(url: String) -> Result<(String, Option), String> { - let metadata = meta_fetcher - ::fetch_metadata(&url) - .map_err(|e| format!("Failed to fetch metadata: {}", e))?; - - Ok((metadata.title.unwrap_or_else(|| "No title found".to_string()), metadata.image)) -} +use applications::{AppInfoContext, AppInfo, AppTrait, utils::image::RustImage}; +use base64::{ engine::general_purpose::STANDARD, Engine }; +use image::codecs::png::PngEncoder; +use tauri::PhysicalPosition; +use meta_fetcher; + +pub fn center_window_on_current_monitor(window: &tauri::WebviewWindow) { + if + let Some(monitor) = window + .available_monitors() + .unwrap() + .iter() + .find(|m| { + let primary_monitor = window + .primary_monitor() + .unwrap() + .expect("Failed to get primary monitor"); + let mouse_position = primary_monitor.position(); + let monitor_position = m.position(); + let monitor_size = m.size(); + mouse_position.x >= monitor_position.x && + mouse_position.x < monitor_position.x + (monitor_size.width as i32) && + mouse_position.y >= monitor_position.y && + mouse_position.y < monitor_position.y + (monitor_size.height as i32) + }) + { + let monitor_size = monitor.size(); + let window_size = window.outer_size().unwrap(); + + let x = ((monitor_size.width as i32) - (window_size.width as i32)) / 2; + let y = ((monitor_size.height as i32) - (window_size.height as i32)) / 2; + + window + .set_position(PhysicalPosition::new(monitor.position().x + x, monitor.position().y + y)) + .unwrap(); + } +} + +#[tauri::command] +pub fn get_app_info() -> (String, Option) { + println!("Getting app info"); + let mut ctx = AppInfoContext::new(vec![]); + println!("Created AppInfoContext"); + + if let Err(e) = ctx.refresh_apps() { + println!("Failed to refresh apps: {:?}", e); + return ("System".to_string(), None); + } + + println!("Refreshed apps"); + + let result = std::panic::catch_unwind(|| { + match ctx.get_frontmost_application() { + Ok(window) => { + println!("Found frontmost application: {}", window.name); + let name = window.name.clone(); + let icon = window + .load_icon() + .ok() + .and_then(|i| { + println!("Loading icon for {}", name); + i.to_png().ok().map(|png| { + let encoded = STANDARD.encode(png.get_bytes()); + println!("Icon encoded successfully"); + encoded + }) + }); + println!("Returning app info: {} with icon: {}", name, icon.is_some()); + (name, icon) + } + Err(e) => { + println!("Failed to get frontmost application: {:?}", e); + ("System".to_string(), None) + } + } + }); + + match result { + Ok(info) => info, + Err(_) => { + println!("Panic occurred while getting app info"); + ("System".to_string(), None) + } + } +} + +fn _process_icon_to_base64(path: &str) -> Result> { + let img = image::open(path)?; + let resized = img.resize(128, 128, image::imageops::FilterType::Lanczos3); + let mut png_buffer = Vec::new(); + resized.write_with_encoder(PngEncoder::new(&mut png_buffer))?; + Ok(STANDARD.encode(png_buffer)) +} + +pub fn detect_color(color: &str) -> bool { + let color = color.trim().to_lowercase(); + + // hex + if color.starts_with('#') && color.len() == color.trim_end_matches(char::is_whitespace).len() { + let hex = &color[1..]; + return match hex.len() { + 3 | 6 | 8 => hex.chars().all(|c| c.is_ascii_hexdigit()), + _ => false, + }; + } + + // rgb/rgba + if + (color.starts_with("rgb(") || color.starts_with("rgba(")) && + color.ends_with(")") && + !color[..color.len() - 1].contains(")") + { + let values = color + .trim_start_matches("rgba(") + .trim_start_matches("rgb(") + .trim_end_matches(')') + .split(',') + .collect::>(); + + return match values.len() { + 3 | 4 => values.iter().all(|v| v.trim().parse::().is_ok()), + _ => false, + }; + } + + // hsl/hsla + if + (color.starts_with("hsl(") || color.starts_with("hsla(")) && + color.ends_with(")") && + !color[..color.len() - 1].contains(")") + { + let values = color + .trim_start_matches("hsla(") + .trim_start_matches("hsl(") + .trim_end_matches(')') + .split(',') + .collect::>(); + + return match values.len() { + 3 | 4 => values.iter().all(|v| v.trim().parse::().is_ok()), + _ => false, + }; + } + + false +} + +#[tauri::command] +pub async fn fetch_page_meta(url: String) -> Result<(String, Option), String> { + let metadata = meta_fetcher + ::fetch_metadata(&url) + .map_err(|e| format!("Failed to fetch metadata: {}", e))?; + + Ok((metadata.title.unwrap_or_else(|| "No title found".to_string()), metadata.image)) +} diff --git a/src-tauri/src/utils/favicon.rs b/src-tauri/src/utils/favicon.rs index 45568dc..d3a8227 100644 --- a/src-tauri/src/utils/favicon.rs +++ b/src-tauri/src/utils/favicon.rs @@ -1,23 +1,23 @@ -use base64::engine::general_purpose::STANDARD; -use base64::Engine; -use image::ImageFormat; -use reqwest; -use url::Url; - -pub async fn fetch_favicon_as_base64( - url: Url -) -> Result, Box> { - let client = reqwest::Client::new(); - let favicon_url = format!("https://favicone.com/{}", url.host_str().unwrap()); - let response = client.get(&favicon_url).send().await?; - - if response.status().is_success() { - let bytes = response.bytes().await?; - let img = image::load_from_memory(&bytes)?; - let mut png_bytes: Vec = Vec::new(); - img.write_to(&mut std::io::Cursor::new(&mut png_bytes), ImageFormat::Png)?; - Ok(Some(STANDARD.encode(&png_bytes))) - } else { - Ok(None) - } -} +use base64::engine::general_purpose::STANDARD; +use base64::Engine; +use image::ImageFormat; +use reqwest; +use url::Url; + +pub async fn fetch_favicon_as_base64( + url: Url +) -> Result, Box> { + let client = reqwest::Client::new(); + let favicon_url = format!("https://favicone.com/{}", url.host_str().unwrap()); + let response = client.get(&favicon_url).send().await?; + + if response.status().is_success() { + let bytes = response.bytes().await?; + let img = image::load_from_memory(&bytes)?; + let mut png_bytes: Vec = Vec::new(); + img.write_to(&mut std::io::Cursor::new(&mut png_bytes), ImageFormat::Png)?; + Ok(Some(STANDARD.encode(&png_bytes))) + } else { + Ok(None) + } +} diff --git a/src-tauri/src/utils/keys.rs b/src-tauri/src/utils/keys.rs index 01b6836..aa331ea 100644 --- a/src-tauri/src/utils/keys.rs +++ b/src-tauri/src/utils/keys.rs @@ -1,120 +1,120 @@ -use global_hotkey::hotkey::Code; -use std::str::FromStr; - -pub struct KeyCode(Code); - -impl FromStr for KeyCode { - type Err = String; - - fn from_str(s: &str) -> Result { - let code = match s { - "Backquote" => Code::Backquote, - "Backslash" => Code::Backslash, - "BracketLeft" => Code::BracketLeft, - "BracketRight" => Code::BracketRight, - "Comma" => Code::Comma, - "Digit0" => Code::Digit0, - "Digit1" => Code::Digit1, - "Digit2" => Code::Digit2, - "Digit3" => Code::Digit3, - "Digit4" => Code::Digit4, - "Digit5" => Code::Digit5, - "Digit6" => Code::Digit6, - "Digit7" => Code::Digit7, - "Digit8" => Code::Digit8, - "Digit9" => Code::Digit9, - "Equal" => Code::Equal, - "KeyA" => Code::KeyA, - "KeyB" => Code::KeyB, - "KeyC" => Code::KeyC, - "KeyD" => Code::KeyD, - "KeyE" => Code::KeyE, - "KeyF" => Code::KeyF, - "KeyG" => Code::KeyG, - "KeyH" => Code::KeyH, - "KeyI" => Code::KeyI, - "KeyJ" => Code::KeyJ, - "KeyK" => Code::KeyK, - "KeyL" => Code::KeyL, - "KeyM" => Code::KeyM, - "KeyN" => Code::KeyN, - "KeyO" => Code::KeyO, - "KeyP" => Code::KeyP, - "KeyQ" => Code::KeyQ, - "KeyR" => Code::KeyR, - "KeyS" => Code::KeyS, - "KeyT" => Code::KeyT, - "KeyU" => Code::KeyU, - "KeyV" => Code::KeyV, - "KeyW" => Code::KeyW, - "KeyX" => Code::KeyX, - "KeyY" => Code::KeyY, - "KeyZ" => Code::KeyZ, - "Minus" => Code::Minus, - "Period" => Code::Period, - "Quote" => Code::Quote, - "Semicolon" => Code::Semicolon, - "Slash" => Code::Slash, - "Backspace" => Code::Backspace, - "CapsLock" => Code::CapsLock, - "Delete" => Code::Delete, - "Enter" => Code::Enter, - "Space" => Code::Space, - "Tab" => Code::Tab, - "End" => Code::End, - "Home" => Code::Home, - "Insert" => Code::Insert, - "PageDown" => Code::PageDown, - "PageUp" => Code::PageUp, - "ArrowDown" => Code::ArrowDown, - "ArrowLeft" => Code::ArrowLeft, - "ArrowRight" => Code::ArrowRight, - "ArrowUp" => Code::ArrowUp, - "NumLock" => Code::NumLock, - "Numpad0" => Code::Numpad0, - "Numpad1" => Code::Numpad1, - "Numpad2" => Code::Numpad2, - "Numpad3" => Code::Numpad3, - "Numpad4" => Code::Numpad4, - "Numpad5" => Code::Numpad5, - "Numpad6" => Code::Numpad6, - "Numpad7" => Code::Numpad7, - "Numpad8" => Code::Numpad8, - "Numpad9" => Code::Numpad9, - "NumpadAdd" => Code::NumpadAdd, - "NumpadDecimal" => Code::NumpadDecimal, - "NumpadDivide" => Code::NumpadDivide, - "NumpadMultiply" => Code::NumpadMultiply, - "NumpadSubtract" => Code::NumpadSubtract, - "Escape" => Code::Escape, - "PrintScreen" => Code::PrintScreen, - "ScrollLock" => Code::ScrollLock, - "Pause" => Code::Pause, - "AudioVolumeDown" => Code::AudioVolumeDown, - "AudioVolumeMute" => Code::AudioVolumeMute, - "AudioVolumeUp" => Code::AudioVolumeUp, - "F1" => Code::F1, - "F2" => Code::F2, - "F3" => Code::F3, - "F4" => Code::F4, - "F5" => Code::F5, - "F6" => Code::F6, - "F7" => Code::F7, - "F8" => Code::F8, - "F9" => Code::F9, - "F10" => Code::F10, - "F11" => Code::F11, - "F12" => Code::F12, - _ => { - return Err(format!("Unknown key code: {}", s)); - } - }; - Ok(KeyCode(code)) - } -} - -impl From for Code { - fn from(key_code: KeyCode) -> Self { - key_code.0 - } -} +use global_hotkey::hotkey::Code; +use std::str::FromStr; + +pub struct KeyCode(Code); + +impl FromStr for KeyCode { + type Err = String; + + fn from_str(s: &str) -> Result { + let code = match s { + "Backquote" => Code::Backquote, + "Backslash" => Code::Backslash, + "BracketLeft" => Code::BracketLeft, + "BracketRight" => Code::BracketRight, + "Comma" => Code::Comma, + "Digit0" => Code::Digit0, + "Digit1" => Code::Digit1, + "Digit2" => Code::Digit2, + "Digit3" => Code::Digit3, + "Digit4" => Code::Digit4, + "Digit5" => Code::Digit5, + "Digit6" => Code::Digit6, + "Digit7" => Code::Digit7, + "Digit8" => Code::Digit8, + "Digit9" => Code::Digit9, + "Equal" => Code::Equal, + "KeyA" => Code::KeyA, + "KeyB" => Code::KeyB, + "KeyC" => Code::KeyC, + "KeyD" => Code::KeyD, + "KeyE" => Code::KeyE, + "KeyF" => Code::KeyF, + "KeyG" => Code::KeyG, + "KeyH" => Code::KeyH, + "KeyI" => Code::KeyI, + "KeyJ" => Code::KeyJ, + "KeyK" => Code::KeyK, + "KeyL" => Code::KeyL, + "KeyM" => Code::KeyM, + "KeyN" => Code::KeyN, + "KeyO" => Code::KeyO, + "KeyP" => Code::KeyP, + "KeyQ" => Code::KeyQ, + "KeyR" => Code::KeyR, + "KeyS" => Code::KeyS, + "KeyT" => Code::KeyT, + "KeyU" => Code::KeyU, + "KeyV" => Code::KeyV, + "KeyW" => Code::KeyW, + "KeyX" => Code::KeyX, + "KeyY" => Code::KeyY, + "KeyZ" => Code::KeyZ, + "Minus" => Code::Minus, + "Period" => Code::Period, + "Quote" => Code::Quote, + "Semicolon" => Code::Semicolon, + "Slash" => Code::Slash, + "Backspace" => Code::Backspace, + "CapsLock" => Code::CapsLock, + "Delete" => Code::Delete, + "Enter" => Code::Enter, + "Space" => Code::Space, + "Tab" => Code::Tab, + "End" => Code::End, + "Home" => Code::Home, + "Insert" => Code::Insert, + "PageDown" => Code::PageDown, + "PageUp" => Code::PageUp, + "ArrowDown" => Code::ArrowDown, + "ArrowLeft" => Code::ArrowLeft, + "ArrowRight" => Code::ArrowRight, + "ArrowUp" => Code::ArrowUp, + "NumLock" => Code::NumLock, + "Numpad0" => Code::Numpad0, + "Numpad1" => Code::Numpad1, + "Numpad2" => Code::Numpad2, + "Numpad3" => Code::Numpad3, + "Numpad4" => Code::Numpad4, + "Numpad5" => Code::Numpad5, + "Numpad6" => Code::Numpad6, + "Numpad7" => Code::Numpad7, + "Numpad8" => Code::Numpad8, + "Numpad9" => Code::Numpad9, + "NumpadAdd" => Code::NumpadAdd, + "NumpadDecimal" => Code::NumpadDecimal, + "NumpadDivide" => Code::NumpadDivide, + "NumpadMultiply" => Code::NumpadMultiply, + "NumpadSubtract" => Code::NumpadSubtract, + "Escape" => Code::Escape, + "PrintScreen" => Code::PrintScreen, + "ScrollLock" => Code::ScrollLock, + "Pause" => Code::Pause, + "AudioVolumeDown" => Code::AudioVolumeDown, + "AudioVolumeMute" => Code::AudioVolumeMute, + "AudioVolumeUp" => Code::AudioVolumeUp, + "F1" => Code::F1, + "F2" => Code::F2, + "F3" => Code::F3, + "F4" => Code::F4, + "F5" => Code::F5, + "F6" => Code::F6, + "F7" => Code::F7, + "F8" => Code::F8, + "F9" => Code::F9, + "F10" => Code::F10, + "F11" => Code::F11, + "F12" => Code::F12, + _ => { + return Err(format!("Unknown key code: {}", s)); + } + }; + Ok(KeyCode(code)) + } +} + +impl From for Code { + fn from(key_code: KeyCode) -> Self { + key_code.0 + } +} diff --git a/src-tauri/src/utils/logger.rs b/src-tauri/src/utils/logger.rs index d0e95c6..f9f42d0 100644 --- a/src-tauri/src/utils/logger.rs +++ b/src-tauri/src/utils/logger.rs @@ -1,84 +1,84 @@ -use chrono; -use log::{ LevelFilter, SetLoggerError }; -use std::fs::{ File, OpenOptions }; -use std::io::Write; -use std::panic; - -pub struct FileLogger { - file: File, -} - -impl log::Log for FileLogger { - fn enabled(&self, _metadata: &log::Metadata) -> bool { - true - } - - fn log(&self, record: &log::Record) { - if self.enabled(record.metadata()) { - let mut file = self.file.try_clone().expect("Failed to clone file handle"); - - writeln!( - file, - "{} [{:<5}] {}: {} ({}:{})", - chrono::Local::now().format("%Y-%m-%d %H:%M:%S"), - record.level(), - record.target(), - record.args(), - record.file().unwrap_or("unknown"), - record.line().unwrap_or(0) - ).expect("Failed to write to log file"); - } - } - - fn flush(&self) { - self.file.sync_all().expect("Failed to flush log file"); - } -} - -pub fn init_logger(app_data_dir: &std::path::Path) -> Result<(), SetLoggerError> { - let logs_dir = app_data_dir.join("logs"); - std::fs::create_dir_all(&logs_dir).expect("Failed to create logs directory"); - - let log_path = logs_dir.join("app.log"); - let file = OpenOptions::new() - .create(true) - .append(true) - .open(&log_path) - .expect("Failed to open log file"); - - let panic_file = file.try_clone().expect("Failed to clone file handle"); - panic::set_hook( - Box::new(move |panic_info| { - let mut file = panic_file.try_clone().expect("Failed to clone file handle"); - - let location = panic_info - .location() - .map(|loc| format!("{}:{}:{}", loc.file(), loc.line(), loc.column())) - .unwrap_or_else(|| "unknown location".to_string()); - - let message = match panic_info.payload().downcast_ref::<&str>() { - Some(s) => *s, - None => - match panic_info.payload().downcast_ref::() { - Some(s) => s.as_str(), - None => "Unknown panic message", - } - }; - - let _ = writeln!( - file, - "{} [PANIC] rust_panic: {} ({})", - chrono::Local::now().format("%Y-%m-%d %H:%M:%S"), - message, - location - ); - }) - ); - - let logger = Box::new(FileLogger { file }); - unsafe { - log::set_logger_racy(Box::leak(logger))?; - } - log::set_max_level(LevelFilter::Debug); - Ok(()) -} +use chrono; +use log::{ LevelFilter, SetLoggerError }; +use std::fs::{ File, OpenOptions }; +use std::io::Write; +use std::panic; + +pub struct FileLogger { + file: File, +} + +impl log::Log for FileLogger { + fn enabled(&self, _metadata: &log::Metadata) -> bool { + true + } + + fn log(&self, record: &log::Record) { + if self.enabled(record.metadata()) { + let mut file = self.file.try_clone().expect("Failed to clone file handle"); + + writeln!( + file, + "{} [{:<5}] {}: {} ({}:{})", + chrono::Local::now().format("%Y-%m-%d %H:%M:%S"), + record.level(), + record.target(), + record.args(), + record.file().unwrap_or("unknown"), + record.line().unwrap_or(0) + ).expect("Failed to write to log file"); + } + } + + fn flush(&self) { + self.file.sync_all().expect("Failed to flush log file"); + } +} + +pub fn init_logger(app_data_dir: &std::path::Path) -> Result<(), SetLoggerError> { + let logs_dir = app_data_dir.join("logs"); + std::fs::create_dir_all(&logs_dir).expect("Failed to create logs directory"); + + let log_path = logs_dir.join("app.log"); + let file = OpenOptions::new() + .create(true) + .append(true) + .open(&log_path) + .expect("Failed to open log file"); + + let panic_file = file.try_clone().expect("Failed to clone file handle"); + panic::set_hook( + Box::new(move |panic_info| { + let mut file = panic_file.try_clone().expect("Failed to clone file handle"); + + let location = panic_info + .location() + .map(|loc| format!("{}:{}:{}", loc.file(), loc.line(), loc.column())) + .unwrap_or_else(|| "unknown location".to_string()); + + let message = match panic_info.payload().downcast_ref::<&str>() { + Some(s) => *s, + None => + match panic_info.payload().downcast_ref::() { + Some(s) => s.as_str(), + None => "Unknown panic message", + } + }; + + let _ = writeln!( + file, + "{} [PANIC] rust_panic: {} ({})", + chrono::Local::now().format("%Y-%m-%d %H:%M:%S"), + message, + location + ); + }) + ); + + let logger = Box::new(FileLogger { file }); + unsafe { + log::set_logger_racy(Box::leak(logger))?; + } + log::set_max_level(LevelFilter::Debug); + Ok(()) +} diff --git a/src-tauri/src/utils/mod.rs b/src-tauri/src/utils/mod.rs index 78e50cb..43e1c56 100644 --- a/src-tauri/src/utils/mod.rs +++ b/src-tauri/src/utils/mod.rs @@ -1,5 +1,5 @@ -pub mod commands; -pub mod favicon; -pub mod types; -pub mod logger; -pub mod keys; +pub mod commands; +pub mod favicon; +pub mod types; +pub mod logger; +pub mod keys; diff --git a/src-tauri/src/utils/types.rs b/src-tauri/src/utils/types.rs index 4e6886f..bc36f9d 100644 --- a/src-tauri/src/utils/types.rs +++ b/src-tauri/src/utils/types.rs @@ -1,155 +1,155 @@ -use chrono::{ DateTime, Utc }; -use serde::{ Deserialize, Serialize }; -use std::fmt; -use uuid::Uuid; - -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] -pub struct HistoryItem { - pub id: String, - pub source: String, - pub source_icon: Option, - pub content_type: ContentType, - pub content: String, - pub favicon: Option, - pub timestamp: DateTime, - pub language: Option, -} - -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] -#[serde(rename_all = "lowercase")] -pub enum ContentType { - Text, - Image, - File, - Link, - Color, - Code, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct InfoText { - pub source: String, - pub content_type: ContentType, - pub characters: i32, - pub words: i32, - pub copied: DateTime, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct InfoImage { - pub source: String, - pub content_type: ContentType, - pub dimensions: String, - pub size: i64, - pub copied: DateTime, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct InfoFile { - pub source: String, - pub content_type: ContentType, - pub path: String, - pub filesize: i64, - pub copied: DateTime, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct InfoLink { - pub source: String, - pub content_type: ContentType, - pub title: Option, - pub url: String, - pub characters: i32, - pub copied: DateTime, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct InfoColor { - pub source: String, - pub content_type: ContentType, - pub hex: String, - pub rgb: String, - pub copied: DateTime, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct InfoCode { - pub source: String, - pub content_type: ContentType, - pub language: String, - pub lines: i32, - pub copied: DateTime, -} - -impl fmt::Display for ContentType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - ContentType::Text => write!(f, "text"), - ContentType::Image => write!(f, "image"), - ContentType::File => write!(f, "file"), - ContentType::Link => write!(f, "link"), - ContentType::Color => write!(f, "color"), - ContentType::Code => write!(f, "code"), - } - } -} - -impl From for ContentType { - fn from(s: String) -> Self { - match s.to_lowercase().as_str() { - "text" => ContentType::Text, - "image" => ContentType::Image, - "file" => ContentType::File, - "link" => ContentType::Link, - "color" => ContentType::Color, - "code" => ContentType::Code, - _ => ContentType::Text, - } - } -} - -impl HistoryItem { - pub fn new( - source: String, - content_type: ContentType, - content: String, - favicon: Option, - source_icon: Option, - language: Option - ) -> Self { - Self { - id: Uuid::new_v4().to_string(), - source, - source_icon, - content_type, - content, - favicon, - timestamp: Utc::now(), - language, - } - } - - pub fn to_row( - &self - ) -> ( - String, - String, - Option, - String, - String, - Option, - DateTime, - Option, - ) { - ( - self.id.clone(), - self.source.clone(), - self.source_icon.clone(), - self.content_type.to_string(), - self.content.clone(), - self.favicon.clone(), - self.timestamp, - self.language.clone(), - ) - } -} +use chrono::{ DateTime, Utc }; +use serde::{ Deserialize, Serialize }; +use std::fmt; +use uuid::Uuid; + +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] +pub struct HistoryItem { + pub id: String, + pub source: String, + pub source_icon: Option, + pub content_type: ContentType, + pub content: String, + pub favicon: Option, + pub timestamp: DateTime, + pub language: Option, +} + +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] +#[serde(rename_all = "lowercase")] +pub enum ContentType { + Text, + Image, + File, + Link, + Color, + Code, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct InfoText { + pub source: String, + pub content_type: ContentType, + pub characters: i32, + pub words: i32, + pub copied: DateTime, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct InfoImage { + pub source: String, + pub content_type: ContentType, + pub dimensions: String, + pub size: i64, + pub copied: DateTime, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct InfoFile { + pub source: String, + pub content_type: ContentType, + pub path: String, + pub filesize: i64, + pub copied: DateTime, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct InfoLink { + pub source: String, + pub content_type: ContentType, + pub title: Option, + pub url: String, + pub characters: i32, + pub copied: DateTime, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct InfoColor { + pub source: String, + pub content_type: ContentType, + pub hex: String, + pub rgb: String, + pub copied: DateTime, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct InfoCode { + pub source: String, + pub content_type: ContentType, + pub language: String, + pub lines: i32, + pub copied: DateTime, +} + +impl fmt::Display for ContentType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ContentType::Text => write!(f, "text"), + ContentType::Image => write!(f, "image"), + ContentType::File => write!(f, "file"), + ContentType::Link => write!(f, "link"), + ContentType::Color => write!(f, "color"), + ContentType::Code => write!(f, "code"), + } + } +} + +impl From for ContentType { + fn from(s: String) -> Self { + match s.to_lowercase().as_str() { + "text" => ContentType::Text, + "image" => ContentType::Image, + "file" => ContentType::File, + "link" => ContentType::Link, + "color" => ContentType::Color, + "code" => ContentType::Code, + _ => ContentType::Text, + } + } +} + +impl HistoryItem { + pub fn new( + source: String, + content_type: ContentType, + content: String, + favicon: Option, + source_icon: Option, + language: Option + ) -> Self { + Self { + id: Uuid::new_v4().to_string(), + source, + source_icon, + content_type, + content, + favicon, + timestamp: Utc::now(), + language, + } + } + + pub fn to_row( + &self + ) -> ( + String, + String, + Option, + String, + String, + Option, + DateTime, + Option, + ) { + ( + self.id.clone(), + self.source.clone(), + self.source_icon.clone(), + self.content_type.to_string(), + self.content.clone(), + self.favicon.clone(), + self.timestamp, + self.language.clone(), + ) + } +} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c6acd3e..fb0305f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,58 +1,58 @@ -{ - "productName": "Qopy", - "version": "0.4.0", - "identifier": "net.pandadev.qopy", - "build": { - "frontendDist": "../dist", - "devUrl": "http://localhost:3000", - "beforeDevCommand": "pnpm nuxt dev", - "beforeBuildCommand": "pnpm nuxt generate" - }, - "app": { - "windows": [ - { - "title": "Qopy", - "titleBarStyle": "Overlay", - "fullscreen": false, - "resizable": false, - "height": 474, - "width": 750, - "minHeight": 474, - "maxHeight": 474, - "minWidth": 750, - "maxWidth": 750, - "decorations": false, - "center": true, - "shadow": false, - "transparent": true, - "skipTaskbar": true, - "alwaysOnTop": true - } - ], - "security": { - "csp": null - }, - "withGlobalTauri": true, - "macOSPrivateApi": true - }, - "bundle": { - "createUpdaterArtifacts": true, - "active": true, - "targets": "all", - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], - "category": "DeveloperTool" - }, - "plugins": { - "updater": { - "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDExNDIzNjA1QjE0NjU1OTkKUldTWlZVYXhCVFpDRWNvNmt0UE5lQmZkblEyZGZiZ2tHelJvT2YvNVpLU1RIM1RKZFQrb2tzWWwK", - "endpoints": ["https://qopy.pandadev.net/"] - } - }, - "$schema": "../node_modules/@tauri-apps/cli/schema.json" -} +{ + "productName": "Qopy", + "version": "0.4.0", + "identifier": "net.pandadev.qopy", + "build": { + "frontendDist": "../dist", + "devUrl": "http://localhost:3000", + "beforeDevCommand": "bun nuxt dev", + "beforeBuildCommand": "bun nuxt generate" + }, + "app": { + "windows": [ + { + "title": "Qopy", + "titleBarStyle": "Overlay", + "fullscreen": false, + "resizable": false, + "height": 474, + "width": 750, + "minHeight": 474, + "maxHeight": 474, + "minWidth": 750, + "maxWidth": 750, + "decorations": false, + "center": true, + "shadow": false, + "transparent": true, + "skipTaskbar": true, + "alwaysOnTop": true + } + ], + "security": { + "csp": null + }, + "withGlobalTauri": true, + "macOSPrivateApi": true + }, + "bundle": { + "createUpdaterArtifacts": true, + "active": true, + "targets": "all", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "category": "DeveloperTool" + }, + "plugins": { + "updater": { + "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDExNDIzNjA1QjE0NjU1OTkKUldTWlZVYXhCVFpDRWNvNmt0UE5lQmZkblEyZGZiZ2tHelJvT2YvNVpLU1RIM1RKZFQrb2tzWWwK", + "endpoints": ["https://qopy.pandadev.net/"] + } + }, + "$schema": "../node_modules/@tauri-apps/cli/schema.json" +} diff --git a/styles/index.scss b/styles/index.scss index 20a154d..9635269 100644 --- a/styles/index.scss +++ b/styles/index.scss @@ -1,186 +1,185 @@ -$primary: #2e2d2b; -$accent: #feb453; -$divider: #ffffff0d; - -$text: #e5dfd5; -$text2: #ada9a1; -$mutedtext: #78756f; - -$search-height: 56px; -$sidebar-width: 286px; -$bottom-bar-height: 39px; -$info-panel-height: 160px; -$content-view-height: calc( - 100% - $search-height - $info-panel-height - $bottom-bar-height -); - -main { - width: 100vw; - height: 100vh; - background-color: $primary; - border: 1px solid $divider; - display: flex; - flex-direction: column; - border-radius: 12px; - justify-content: space-between; -} - -.container { - height: 376px; - width: 100%; - display: flex; -} - -.results { - display: flex; - flex-direction: column; - padding: 14px 8px; - gap: 8px; - min-width: 286px; - border-right: 1px solid var(--border); - - .time-separator { - font-size: 12px; - color: $text2; - font-family: SFRoundedSemiBold; - padding-left: 8px; - } - - .group { - & + .group { - margin-top: 16px; - } - - .time-separator { - margin-bottom: 8px; - } - - .results-group { - display: flex; - flex-direction: column; - } - } - - .favicon, - .image, - .icon { - width: 18px; - height: 18px; - } -} - -.right { - display: flex; - flex-direction: column; - width: 100%; -} - -.content { - height: 100%; - font-family: CommitMono !important; - font-size: 12px; - letter-spacing: 1; - border-radius: 10px; - width: 462px; - display: flex; - flex-direction: column; - align-items: flex-start; - overflow: hidden; - z-index: 2; - color: $text; - - &:not(:has(.image)) { - padding: 8px; - } - - span.content-text { - font-family: CommitMono !important; - white-space: pre-wrap; - word-wrap: break-word; - word-break: break-word; - max-width: 100%; - } - - .image { - width: 100%; - height: 100%; - object-fit: contain; - object-position: center; - } -} - -.information { - min-height: 160px; - width: 462px; - border-top: 1px solid $divider; - padding: 14px; - z-index: 1; - display: flex; - flex-direction: column; - gap: 14px; - - .title { - font-family: SFRoundedSemiBold; - font-size: 12px; - letter-spacing: 0.6px; - color: $text; - } - - .info-content { - display: flex; - gap: 0; - flex-direction: column; - - .info-row { - display: flex; - width: 100%; - font-size: 12px; - justify-content: space-between; - padding: 8px 0; - border-bottom: 1px solid $divider; - line-height: 1; - - &:last-child { - border-bottom: none; - padding-bottom: 0; - } - - &:first-child { - padding-top: 22px; - } - - p { - font-family: SFRoundedMedium; - color: $text2; - font-weight: 500; - flex-shrink: 0; - } - - span { - font-family: CommitMono; - color: $text; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - margin-left: 32px; - display: flex; - align-items: center; - gap: 4px; - - img { - width: 13px; - height: 13px; - object-fit: contain; - } - } - } - } -} - -.search-loading { - display: flex; - justify-content: center; - padding: 20px; - font-size: 16px; - color: var(--text-secondary); +$primary: #2e2d2b; +$accent: #feb453; +$divider: #ffffff0d; + +$text: #e5dfd5; +$text2: #ada9a1; +$mutedtext: #78756f; + +$search-height: 56px; +$sidebar-width: 286px; +$bottom-bar-height: 39px; +$info-panel-height: 160px; +$content-view-height: calc( + 100% - $search-height - $info-panel-height - $bottom-bar-height +); + +main { + width: 100vw; + height: 100vh; + background-color: $primary; + border: 1px solid $divider; + display: flex; + flex-direction: column; + border-radius: 12px; + justify-content: space-between; +} + +.container { + height: 376px; + width: 100%; + display: flex; +} + +.results { + display: flex; + flex-direction: column; + padding: 14px 8px; + gap: 8px; + min-width: 286px; + border-right: 1px solid var(--border); + + .time-separator { + font-size: 12px; + color: $text2; + font-family: SFRoundedSemiBold; + padding-left: 8px; + } + + .group { + & + .group { + margin-top: 16px; + } + + .time-separator { + margin-bottom: 8px; + } + + .results-group { + display: flex; + flex-direction: column; + } + } + + .favicon, + .image, + .icon { + width: 18px; + height: 18px; + } +} + +.right { + display: flex; + flex-direction: column; + width: 100%; +} + +.content { + height: 100%; + font-family: CommitMono !important; + font-size: 12px; + letter-spacing: 1; + border-radius: 10px; + width: 462px; + display: flex; + flex-direction: column; + align-items: flex-start; + overflow: hidden; + z-index: 2; + color: $text; + + &:not(:has(.image)) { + padding: 8px; + } + + span.content-text { + font-family: CommitMono !important; + white-space: pre-wrap; + word-wrap: break-word; + word-break: break-word; + max-width: 100%; + } + + .image { + width: 100%; + height: 100%; + object-fit: contain; + object-position: center; + } +} + +.information { + min-height: 160px; + width: 462px; + border-top: 1px solid $divider; + padding: 14px; + z-index: 1; + display: flex; + flex-direction: column; + gap: 14px; + + .title { + font-family: SFRoundedSemiBold; + font-size: 12px; + letter-spacing: 0.6px; + color: $text; + } + + .info-content { + display: flex; + gap: 0; + flex-direction: column; + + .info-row { + display: flex; + width: 100%; + font-size: 12px; + justify-content: space-between; + padding: 8px 0; + border-bottom: 1px solid $divider; + + &:last-child { + border-bottom: none; + padding-bottom: 0; + } + + &:first-child { + padding-top: 14px; + } + + p { + font-family: SFRoundedMedium; + color: $text2; + font-weight: 500; + flex-shrink: 0; + } + + span { + font-family: CommitMono; + color: $text; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + margin-left: 32px; + display: flex; + align-items: center; + gap: 4px; + + img { + width: 13px; + height: 13px; + object-fit: contain; + } + } + } + } +} + +.search-loading { + display: flex; + justify-content: center; + padding: 20px; + font-size: 16px; + color: var(--text-secondary); } \ No newline at end of file diff --git a/styles/settings.scss b/styles/settings.scss index 1f0b682..500eab9 100644 --- a/styles/settings.scss +++ b/styles/settings.scss @@ -1,235 +1,235 @@ -$primary: #2e2d2b; -$accent: #feb453; -$divider: #ffffff0d; - -$text: #e5dfd5; -$text2: #ada9a1; -$mutedtext: #78756f; - -main { - width: 100vw; - height: 100vh; - background-color: $primary; - border: 1px solid $divider; - display: flex; - flex-direction: column; - border-radius: 12px; - justify-content: space-between; -} - -.back { - position: absolute; - top: 16px; - left: 16px; - display: flex; - gap: 8px; - align-items: center; - - img { - background-color: $divider; - border-radius: 6px; - padding: 8px 6px; - } - - p { - color: $text2; - } -} - -p { - font-family: SFRoundedMedium; -} - -.settings-container { - width: 100%; - height: 100%; - margin-top: 26px; - position: relative; - font-size: 12px; - font-family: SFRoundedMedium; - - .settings { - position: absolute; - left: 50%; - transform: translateX(-50%); - margin-left: -26px; - display: flex; - gap: 24px; - - .names { - display: flex; - flex-direction: column; - gap: 16px; - - p { - font-family: SFRoundedSemiBold; - color: $text2; - display: flex; - justify-content: right; - } - } - - .actions { - display: flex; - flex-direction: column; - gap: 16px; - color: $mutedtext; - } - } -} - -.launch { - display: flex; - align-items: center; - gap: 6px; - - input[type="checkbox"] { - appearance: none; - width: 14px; - height: 14px; - background-color: transparent; - border-radius: 5px; - border: 1px solid $mutedtext; - position: relative; - cursor: pointer; - transition: background-color 0.2s; - - &:checked { - ~ .checkmark { - opacity: 1; - } - } - } - - .checkmark { - height: 14px; - width: 14px; - position: absolute; - opacity: 0; - transition: opacity 0.2s; - } - - p { - color: $text2; - } -} - -.keybind-input { - width: min-content; - white-space: nowrap; - padding: 6px; - border: 1px solid $divider; - color: $text2; - display: flex; - border-radius: 10px; - outline: none; - gap: 4px; - - .key { - color: $text2; - font-family: SFRoundedMedium; - background-color: $divider; - padding: 2px 6px; - border-radius: 6px; - font-size: 14px; - } -} - -.keybind-input:focus { - border: 1px solid rgba(255, 255, 255, 0.2); -} - -.empty-keybind { - border-color: rgba(255, 82, 82, 0.298); -} - -.top-bar { - width: 100%; - min-height: 56px; - border-bottom: 1px solid $divider; -} - -.bottom-bar { - height: 40px; - width: calc(100vw - 2px); - backdrop-filter: blur(18px); - background-color: hsla(40, 3%, 16%, 0.8); - position: fixed; - bottom: 1px; - left: 1px; - z-index: 100; - border-radius: 0 0 12px 12px; - display: flex; - flex-direction: row; - justify-content: space-between; - padding-inline: 12px; - padding-right: 6px; - padding-top: 1px; - align-items: center; - font-size: 14px; - border-top: 1px solid $divider; - - p { - color: $text2; - } - - .left { - display: flex; - align-items: center; - gap: 8px; - - .logo { - width: 18px; - height: 18px; - } - } - - .right { - display: flex; - align-items: center; - - .actions div { - display: flex; - align-items: center; - gap: 2px; - } - - .divider { - width: 2px; - height: 12px; - background-color: $divider; - margin-left: 8px; - margin-right: 4px; - transition: all 0.2s; - } - - .actions { - padding: 4px; - padding-left: 8px; - display: flex; - align-items: center; - gap: 8px; - border-radius: 7px; - background-color: transparent; - transition: all 0.2s; - cursor: pointer; - - p { - color: $text; - } - - &.disabled { - pointer-events: none; - opacity: 0.5; - } - } - - .actions:hover { - background-color: $divider; - } - - &:hover .actions:hover ~ .divider { - opacity: 0; - } - } -} +$primary: #2e2d2b; +$accent: #feb453; +$divider: #ffffff0d; + +$text: #e5dfd5; +$text2: #ada9a1; +$mutedtext: #78756f; + +main { + width: 100vw; + height: 100vh; + background-color: $primary; + border: 1px solid $divider; + display: flex; + flex-direction: column; + border-radius: 12px; + justify-content: space-between; +} + +.back { + position: absolute; + top: 16px; + left: 16px; + display: flex; + gap: 8px; + align-items: center; + + img { + background-color: $divider; + border-radius: 6px; + padding: 8px 6px; + } + + p { + color: $text2; + } +} + +p { + font-family: SFRoundedMedium; +} + +.settings-container { + width: 100%; + height: 100%; + margin-top: 26px; + position: relative; + font-size: 12px; + font-family: SFRoundedMedium; + + .settings { + position: absolute; + left: 50%; + transform: translateX(-50%); + margin-left: -26px; + display: flex; + gap: 24px; + + .names { + display: flex; + flex-direction: column; + gap: 16px; + + p { + font-family: SFRoundedSemiBold; + color: $text2; + display: flex; + justify-content: right; + } + } + + .actions { + display: flex; + flex-direction: column; + gap: 16px; + color: $mutedtext; + } + } +} + +.launch { + display: flex; + align-items: center; + gap: 6px; + + input[type="checkbox"] { + appearance: none; + width: 14px; + height: 14px; + background-color: transparent; + border-radius: 5px; + border: 1px solid $mutedtext; + position: relative; + cursor: pointer; + transition: background-color 0.2s; + + &:checked { + ~ .checkmark { + opacity: 1; + } + } + } + + .checkmark { + height: 14px; + width: 14px; + position: absolute; + opacity: 0; + transition: opacity 0.2s; + } + + p { + color: $text2; + } +} + +.keybind-input { + width: min-content; + white-space: nowrap; + padding: 6px; + border: 1px solid $divider; + color: $text2; + display: flex; + border-radius: 10px; + outline: none; + gap: 4px; + + .key { + color: $text2; + font-family: SFRoundedMedium; + background-color: $divider; + padding: 2px 6px; + border-radius: 6px; + font-size: 14px; + } +} + +.keybind-input:focus { + border: 1px solid rgba(255, 255, 255, 0.2); +} + +.empty-keybind { + border-color: rgba(255, 82, 82, 0.298); +} + +.top-bar { + width: 100%; + min-height: 56px; + border-bottom: 1px solid $divider; +} + +.bottom-bar { + height: 40px; + width: calc(100vw - 2px); + backdrop-filter: blur(18px); + background-color: hsla(40, 3%, 16%, 0.8); + position: fixed; + bottom: 1px; + left: 1px; + z-index: 100; + border-radius: 0 0 12px 12px; + display: flex; + flex-direction: row; + justify-content: space-between; + padding-inline: 12px; + padding-right: 6px; + padding-top: 1px; + align-items: center; + font-size: 14px; + border-top: 1px solid $divider; + + p { + color: $text2; + } + + .left { + display: flex; + align-items: center; + gap: 8px; + + .logo { + width: 18px; + height: 18px; + } + } + + .right { + display: flex; + align-items: center; + + .actions div { + display: flex; + align-items: center; + gap: 2px; + } + + .divider { + width: 2px; + height: 12px; + background-color: $divider; + margin-left: 8px; + margin-right: 4px; + transition: all 0.2s; + } + + .actions { + padding: 4px; + padding-left: 8px; + display: flex; + align-items: center; + gap: 8px; + border-radius: 7px; + background-color: transparent; + transition: all 0.2s; + cursor: pointer; + + p { + color: $text; + } + + &.disabled { + pointer-events: none; + opacity: 0.5; + } + } + + .actions:hover { + background-color: $divider; + } + + &:hover .actions:hover ~ .divider { + opacity: 0; + } + } +} diff --git a/tsconfig.json b/tsconfig.json index a746f2a..2c4dd59 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,4 @@ -{ - // https://nuxt.com/docs/guide/concepts/typescript - "extends": "./.nuxt/tsconfig.json" -} +{ + // https://nuxt.com/docs/guide/concepts/typescript + "extends": "./.nuxt/tsconfig.json" +} diff --git a/types/keyboard.d.ts b/types/keyboard.d.ts new file mode 100644 index 0000000..8024ffa --- /dev/null +++ b/types/keyboard.d.ts @@ -0,0 +1,27 @@ +import type { Key as WaraduKey, useKeyboard } from '@waradu/keyboard'; + +declare module '#app' { + interface NuxtApp { + $keyboard: { + listen: ReturnType['listen']; + init: ReturnType['init']; + Key: typeof WaraduKey; + currentOS: string; + clearAll: () => void; + }; + } +} + +declare module 'vue' { + interface ComponentCustomProperties { + $keyboard: { + listen: ReturnType['listen']; + init: ReturnType['init']; + Key: typeof WaraduKey; + currentOS: string; + clearAll: () => void; + }; + } +} + +export {}; \ No newline at end of file diff --git a/types/keys.ts b/types/keys.ts index d81454f..a94b7b7 100644 --- a/types/keys.ts +++ b/types/keys.ts @@ -1,217 +1,217 @@ -export enum KeyValues { - Backquote = 'Backquote', - Backslash = 'Backslash', - BracketLeft = 'BracketLeft', - BracketRight = 'BracketRight', - Comma = 'Comma', - Digit0 = 'Digit0', - Digit1 = 'Digit1', - Digit2 = 'Digit2', - Digit3 = 'Digit3', - Digit4 = 'Digit4', - Digit5 = 'Digit5', - Digit6 = 'Digit6', - Digit7 = 'Digit7', - Digit8 = 'Digit8', - Digit9 = 'Digit9', - Equal = 'Equal', - KeyA = 'KeyA', - KeyB = 'KeyB', - KeyC = 'KeyC', - KeyD = 'KeyD', - KeyE = 'KeyE', - KeyF = 'KeyF', - KeyG = 'KeyG', - KeyH = 'KeyH', - KeyI = 'KeyI', - KeyJ = 'KeyJ', - KeyK = 'KeyK', - KeyL = 'KeyL', - KeyM = 'KeyM', - KeyN = 'KeyN', - KeyO = 'KeyO', - KeyP = 'KeyP', - KeyQ = 'KeyQ', - KeyR = 'KeyR', - KeyS = 'KeyS', - KeyT = 'KeyT', - KeyU = 'KeyU', - KeyV = 'KeyV', - KeyW = 'KeyW', - KeyX = 'KeyX', - KeyY = 'KeyY', - KeyZ = 'KeyZ', - Minus = 'Minus', - Period = 'Period', - Quote = 'Quote', - Semicolon = 'Semicolon', - Slash = 'Slash', - AltLeft = 'AltLeft', - AltRight = 'AltRight', - Backspace = 'Backspace', - CapsLock = 'CapsLock', - ContextMenu = 'ContextMenu', - ControlLeft = 'ControlLeft', - ControlRight = 'ControlRight', - Enter = 'Enter', - MetaLeft = 'MetaLeft', - MetaRight = 'MetaRight', - ShiftLeft = 'ShiftLeft', - ShiftRight = 'ShiftRight', - Space = 'Space', - Tab = 'Tab', - Delete = 'Delete', - End = 'End', - Home = 'Home', - Insert = 'Insert', - PageDown = 'PageDown', - PageUp = 'PageUp', - ArrowDown = 'ArrowDown', - ArrowLeft = 'ArrowLeft', - ArrowRight = 'ArrowRight', - ArrowUp = 'ArrowUp', - NumLock = 'NumLock', - Numpad0 = 'Numpad0', - Numpad1 = 'Numpad1', - Numpad2 = 'Numpad2', - Numpad3 = 'Numpad3', - Numpad4 = 'Numpad4', - Numpad5 = 'Numpad5', - Numpad6 = 'Numpad6', - Numpad7 = 'Numpad7', - Numpad8 = 'Numpad8', - Numpad9 = 'Numpad9', - NumpadAdd = 'NumpadAdd', - NumpadDecimal = 'NumpadDecimal', - NumpadDivide = 'NumpadDivide', - NumpadMultiply = 'NumpadMultiply', - NumpadSubtract = 'NumpadSubtract', - Escape = 'Escape', - PrintScreen = 'PrintScreen', - ScrollLock = 'ScrollLock', - Pause = 'Pause', - AudioVolumeDown = 'AudioVolumeDown', - AudioVolumeMute = 'AudioVolumeMute', - AudioVolumeUp = 'AudioVolumeUp', - F1 = 'F1', - F2 = 'F2', - F3 = 'F3', - F4 = 'F4', - F5 = 'F5', - F6 = 'F6', - F7 = 'F7', - F8 = 'F8', - F9 = 'F9', - F10 = 'F10', - F11 = 'F11', - F12 = 'F12', -} - -export enum KeyLabels { - Backquote = '`', - Backslash = '\\', - BracketLeft = '[', - BracketRight = ']', - Comma = ',', - Digit0 = '0', - Digit1 = '1', - Digit2 = '2', - Digit3 = '3', - Digit4 = '4', - Digit5 = '5', - Digit6 = '6', - Digit7 = '7', - Digit8 = '8', - Digit9 = '9', - Equal = '=', - KeyA = 'A', - KeyB = 'B', - KeyC = 'C', - KeyD = 'D', - KeyE = 'E', - KeyF = 'F', - KeyG = 'G', - KeyH = 'H', - KeyI = 'I', - KeyJ = 'J', - KeyK = 'K', - KeyL = 'L', - KeyM = 'M', - KeyN = 'N', - KeyO = 'O', - KeyP = 'P', - KeyQ = 'Q', - KeyR = 'R', - KeyS = 'S', - KeyT = 'T', - KeyU = 'U', - KeyV = 'V', - KeyW = 'W', - KeyX = 'X', - KeyY = 'Y', - KeyZ = 'Z', - Minus = '-', - Period = '.', - Quote = "'", - Semicolon = ';', - Slash = '/', - AltLeft = 'Alt', - AltRight = 'Alt (Right)', - Backspace = 'Backspace', - CapsLock = 'Caps Lock', - ContextMenu = 'Context Menu', - ControlLeft = 'Ctrl', - ControlRight = 'Ctrl (Right)', - Enter = 'Enter', - MetaLeft = 'Meta', - MetaRight = 'Meta (Right)', - ShiftLeft = 'Shift', - ShiftRight = 'Shift (Right)', - Space = 'Space', - Tab = 'Tab', - Delete = 'Delete', - End = 'End', - Home = 'Home', - Insert = 'Insert', - PageDown = 'Page Down', - PageUp = 'Page Up', - ArrowDown = '↓', - ArrowLeft = '←', - ArrowRight = '→', - ArrowUp = '↑', - NumLock = 'Num Lock', - Numpad0 = 'Numpad 0', - Numpad1 = 'Numpad 1', - Numpad2 = 'Numpad 2', - Numpad3 = 'Numpad 3', - Numpad4 = 'Numpad 4', - Numpad5 = 'Numpad 5', - Numpad6 = 'Numpad 6', - Numpad7 = 'Numpad 7', - Numpad8 = 'Numpad 8', - Numpad9 = 'Numpad 9', - NumpadAdd = 'Numpad +', - NumpadDecimal = 'Numpad .', - NumpadDivide = 'Numpad /', - NumpadMultiply = 'Numpad *', - NumpadSubtract = 'Numpad -', - Escape = 'Esc', - PrintScreen = 'Print Screen', - ScrollLock = 'Scroll Lock', - Pause = 'Pause', - AudioVolumeDown = 'Volume Down', - AudioVolumeMute = 'Volume Mute', - AudioVolumeUp = 'Volume Up', - F1 = 'F1', - F2 = 'F2', - F3 = 'F3', - F4 = 'F4', - F5 = 'F5', - F6 = 'F6', - F7 = 'F7', - F8 = 'F8', - F9 = 'F9', - F10 = 'F10', - F11 = 'F11', - F12 = 'F12', +export enum KeyValues { + Backquote = 'Backquote', + Backslash = 'Backslash', + BracketLeft = 'BracketLeft', + BracketRight = 'BracketRight', + Comma = 'Comma', + Digit0 = 'Digit0', + Digit1 = 'Digit1', + Digit2 = 'Digit2', + Digit3 = 'Digit3', + Digit4 = 'Digit4', + Digit5 = 'Digit5', + Digit6 = 'Digit6', + Digit7 = 'Digit7', + Digit8 = 'Digit8', + Digit9 = 'Digit9', + Equal = 'Equal', + KeyA = 'KeyA', + KeyB = 'KeyB', + KeyC = 'KeyC', + KeyD = 'KeyD', + KeyE = 'KeyE', + KeyF = 'KeyF', + KeyG = 'KeyG', + KeyH = 'KeyH', + KeyI = 'KeyI', + KeyJ = 'KeyJ', + KeyK = 'KeyK', + KeyL = 'KeyL', + KeyM = 'KeyM', + KeyN = 'KeyN', + KeyO = 'KeyO', + KeyP = 'KeyP', + KeyQ = 'KeyQ', + KeyR = 'KeyR', + KeyS = 'KeyS', + KeyT = 'KeyT', + KeyU = 'KeyU', + KeyV = 'KeyV', + KeyW = 'KeyW', + KeyX = 'KeyX', + KeyY = 'KeyY', + KeyZ = 'KeyZ', + Minus = 'Minus', + Period = 'Period', + Quote = 'Quote', + Semicolon = 'Semicolon', + Slash = 'Slash', + AltLeft = 'AltLeft', + AltRight = 'AltRight', + Backspace = 'Backspace', + CapsLock = 'CapsLock', + ContextMenu = 'ContextMenu', + ControlLeft = 'ControlLeft', + ControlRight = 'ControlRight', + Enter = 'Enter', + MetaLeft = 'MetaLeft', + MetaRight = 'MetaRight', + ShiftLeft = 'ShiftLeft', + ShiftRight = 'ShiftRight', + Space = 'Space', + Tab = 'Tab', + Delete = 'Delete', + End = 'End', + Home = 'Home', + Insert = 'Insert', + PageDown = 'PageDown', + PageUp = 'PageUp', + ArrowDown = 'ArrowDown', + ArrowLeft = 'ArrowLeft', + ArrowRight = 'ArrowRight', + ArrowUp = 'ArrowUp', + NumLock = 'NumLock', + Numpad0 = 'Numpad0', + Numpad1 = 'Numpad1', + Numpad2 = 'Numpad2', + Numpad3 = 'Numpad3', + Numpad4 = 'Numpad4', + Numpad5 = 'Numpad5', + Numpad6 = 'Numpad6', + Numpad7 = 'Numpad7', + Numpad8 = 'Numpad8', + Numpad9 = 'Numpad9', + NumpadAdd = 'NumpadAdd', + NumpadDecimal = 'NumpadDecimal', + NumpadDivide = 'NumpadDivide', + NumpadMultiply = 'NumpadMultiply', + NumpadSubtract = 'NumpadSubtract', + Escape = 'Escape', + PrintScreen = 'PrintScreen', + ScrollLock = 'ScrollLock', + Pause = 'Pause', + AudioVolumeDown = 'AudioVolumeDown', + AudioVolumeMute = 'AudioVolumeMute', + AudioVolumeUp = 'AudioVolumeUp', + F1 = 'F1', + F2 = 'F2', + F3 = 'F3', + F4 = 'F4', + F5 = 'F5', + F6 = 'F6', + F7 = 'F7', + F8 = 'F8', + F9 = 'F9', + F10 = 'F10', + F11 = 'F11', + F12 = 'F12', +} + +export enum KeyLabels { + Backquote = '`', + Backslash = '\\', + BracketLeft = '[', + BracketRight = ']', + Comma = ',', + Digit0 = '0', + Digit1 = '1', + Digit2 = '2', + Digit3 = '3', + Digit4 = '4', + Digit5 = '5', + Digit6 = '6', + Digit7 = '7', + Digit8 = '8', + Digit9 = '9', + Equal = '=', + KeyA = 'A', + KeyB = 'B', + KeyC = 'C', + KeyD = 'D', + KeyE = 'E', + KeyF = 'F', + KeyG = 'G', + KeyH = 'H', + KeyI = 'I', + KeyJ = 'J', + KeyK = 'K', + KeyL = 'L', + KeyM = 'M', + KeyN = 'N', + KeyO = 'O', + KeyP = 'P', + KeyQ = 'Q', + KeyR = 'R', + KeyS = 'S', + KeyT = 'T', + KeyU = 'U', + KeyV = 'V', + KeyW = 'W', + KeyX = 'X', + KeyY = 'Y', + KeyZ = 'Z', + Minus = '-', + Period = '.', + Quote = "'", + Semicolon = ';', + Slash = '/', + AltLeft = 'Alt', + AltRight = 'Alt (Right)', + Backspace = 'Backspace', + CapsLock = 'Caps Lock', + ContextMenu = 'Context Menu', + ControlLeft = 'Ctrl', + ControlRight = 'Ctrl (Right)', + Enter = 'Enter', + MetaLeft = 'Meta', + MetaRight = 'Meta (Right)', + ShiftLeft = 'Shift', + ShiftRight = 'Shift (Right)', + Space = 'Space', + Tab = 'Tab', + Delete = 'Delete', + End = 'End', + Home = 'Home', + Insert = 'Insert', + PageDown = 'Page Down', + PageUp = 'Page Up', + ArrowDown = '↓', + ArrowLeft = '←', + ArrowRight = '→', + ArrowUp = '↑', + NumLock = 'Num Lock', + Numpad0 = 'Numpad 0', + Numpad1 = 'Numpad 1', + Numpad2 = 'Numpad 2', + Numpad3 = 'Numpad 3', + Numpad4 = 'Numpad 4', + Numpad5 = 'Numpad 5', + Numpad6 = 'Numpad 6', + Numpad7 = 'Numpad 7', + Numpad8 = 'Numpad 8', + Numpad9 = 'Numpad 9', + NumpadAdd = 'Numpad +', + NumpadDecimal = 'Numpad .', + NumpadDivide = 'Numpad /', + NumpadMultiply = 'Numpad *', + NumpadSubtract = 'Numpad -', + Escape = 'Esc', + PrintScreen = 'Print Screen', + ScrollLock = 'Scroll Lock', + Pause = 'Pause', + AudioVolumeDown = 'Volume Down', + AudioVolumeMute = 'Volume Mute', + AudioVolumeUp = 'Volume Up', + F1 = 'F1', + F2 = 'F2', + F3 = 'F3', + F4 = 'F4', + F5 = 'F5', + F6 = 'F6', + F7 = 'F7', + F8 = 'F8', + F9 = 'F9', + F10 = 'F10', + F11 = 'F11', + F12 = 'F12', } \ No newline at end of file diff --git a/types/types.ts b/types/types.ts index 43cdb16..00568a8 100644 --- a/types/types.ts +++ b/types/types.ts @@ -1,116 +1,116 @@ -import { v4 as uuidv4 } from "uuid"; - -export enum ContentType { - Text = "text", - Image = "image", - File = "file", - Link = "link", - Color = "color", - Code = "code", -} - -export class HistoryItem { - id: string; - source: string; - source_icon?: string; - content_type: ContentType; - content: string; - favicon?: string; - timestamp: Date; - language?: string; - - constructor( - source: string, - content_type: ContentType, - content: string, - favicon?: string, - source_icon?: string, - language?: string - ) { - this.id = uuidv4(); - this.source = source; - this.source_icon = source_icon; - this.content_type = content_type; - this.content = content; - this.favicon = favicon; - this.timestamp = new Date(); - this.language = language; - } - - toRow(): [ - string, - string, - string | undefined, - string, - string, - string | undefined, - Date, - string | undefined - ] { - return [ - this.id, - this.source, - this.source_icon, - this.content_type, - this.content, - this.favicon, - this.timestamp, - this.language, - ]; - } -} - -export interface Settings { - key: string; - value: string; -} - -export interface InfoText { - source: string; - content_type: ContentType.Text; - characters: number; - words: number; - copied: Date; -} - -export interface InfoImage { - source: string; - content_type: ContentType.Image; - dimensions: string; - size: number; - copied: Date; -} - -export interface InfoFile { - source: string; - content_type: ContentType.File; - path: string; - filesize: number; - copied: Date; -} - -export interface InfoLink { - source: string; - content_type: ContentType.Link; - title?: string; - url: string; - characters: number; - copied: Date; -} - -export interface InfoColor { - source: string; - content_type: ContentType.Color; - hex: string; - rgb: string; - hsl: string; - copied: Date; -} - -export interface InfoCode { - source: string; - content_type: ContentType.Code; - language: string; - lines: number; - copied: Date; -} +import { v4 as uuidv4 } from "uuid"; + +export enum ContentType { + Text = "text", + Image = "image", + File = "file", + Link = "link", + Color = "color", + Code = "code", +} + +export class HistoryItem { + id: string; + source: string; + source_icon?: string; + content_type: ContentType; + content: string; + favicon?: string; + timestamp: Date; + language?: string; + + constructor( + source: string, + content_type: ContentType, + content: string, + favicon?: string, + source_icon?: string, + language?: string + ) { + this.id = uuidv4(); + this.source = source; + this.source_icon = source_icon; + this.content_type = content_type; + this.content = content; + this.favicon = favicon; + this.timestamp = new Date(); + this.language = language; + } + + toRow(): [ + string, + string, + string | undefined, + string, + string, + string | undefined, + Date, + string | undefined + ] { + return [ + this.id, + this.source, + this.source_icon, + this.content_type, + this.content, + this.favicon, + this.timestamp, + this.language, + ]; + } +} + +export interface Settings { + key: string; + value: string; +} + +export interface InfoText { + source: string; + content_type: ContentType.Text; + characters: number; + words: number; + copied: Date; +} + +export interface InfoImage { + source: string; + content_type: ContentType.Image; + dimensions: string; + size: number; + copied: Date; +} + +export interface InfoFile { + source: string; + content_type: ContentType.File; + path: string; + filesize: number; + copied: Date; +} + +export interface InfoLink { + source: string; + content_type: ContentType.Link; + title?: string; + url: string; + characters: number; + copied: Date; +} + +export interface InfoColor { + source: string; + content_type: ContentType.Color; + hex: string; + rgb: string; + hsl: string; + copied: Date; +} + +export interface InfoCode { + source: string; + content_type: ContentType.Code; + language: string; + lines: number; + copied: Date; +}