From 741cc51a01d454a00edac25e323b4e170996f2ea Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Sat, 21 Dec 2024 23:54:54 +1000 Subject: [PATCH 001/110] chore: enhance Windows build workflow with multi-architecture support and artifact naming --- .github/workflows/build.yml | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e975560..1a6a900 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -115,6 +115,15 @@ jobs: 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 }} @@ -124,6 +133,8 @@ jobs: 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" @@ -142,18 +153,18 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Rename and Publish Windows Artifacts run: | - mv src-tauri/target/release/bundle/msi/*.msi src-tauri/target/release/bundle/msi/Qopy-${{ needs.prepare.outputs.version }}.msi - mv src-tauri/target/release/bundle/msi/*.msi.sig src-tauri/target/release/bundle/msi/Qopy-${{ needs.prepare.outputs.version }}.msi.sig + 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: build-windows-msi - path: src-tauri/target/release/bundle/msi/*.msi + name: build-windows-msi-${{ matrix.arch }} + path: src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi - uses: actions/upload-artifact@v4 with: - name: updater-files-windows + name: updater-files-windows-${{ matrix.arch }} path: | - src-tauri/target/release/bundle/msi/*.msi - src-tauri/target/release/bundle/msi/*.msi.sig + src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi + src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi.sig build-ubuntu: needs: prepare From ec00adcbb5fc6ee0a6f99813f19c4bdd58f0269e Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Sun, 22 Dec 2024 00:01:34 +1000 Subject: [PATCH 002/110] chore: improve artifact handling in build workflow with enhanced renaming and listing for Windows and Linux --- .github/workflows/build.yml | 79 +++++++++++++++++++++-------------- .github/workflows/release.yml | 53 ++++++++++++----------- 2 files changed, 77 insertions(+), 55 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1a6a900..5d7aaa0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -151,23 +151,46 @@ jobs: - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Rename and Publish Windows Artifacts + - name: List Bundle Directory + shell: pwsh 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 + $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 + } - uses: actions/upload-artifact@v4 with: - name: build-windows-msi-${{ matrix.arch }} + name: windows-${{ matrix.arch }}-binaries path: src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi - - uses: actions/upload-artifact@v4 - with: - name: updater-files-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 + strategy: + matrix: + include: + - target: "x86_64-unknown-linux-gnu" + arch: "x64" + - target: "aarch64-unknown-linux-gnu" + arch: "arm64" runs-on: ubuntu-latest env: TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} @@ -177,6 +200,8 @@ jobs: with: node-version: 20 - uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} - uses: swatinem/rust-cache@v2 with: workspaces: "src-tauri -> target" @@ -192,33 +217,25 @@ jobs: - name: install dependencies run: | sudo apt update - sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file libssl-dev libayatana-appindicator3-dev librsvg2-dev libasound2-dev + 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 }} - - name: Rename and Publish Ubuntu Artifacts + with: + args: --target ${{ matrix.target }} + - name: Rename Linux Artifacts run: | - mv src-tauri/target/release/bundle/deb/*.deb src-tauri/target/release/bundle/deb/Qopy-${{ needs.prepare.outputs.version }}.deb - mv src-tauri/target/release/bundle/appimage/*.AppImage src-tauri/target/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}.AppImage - mv src-tauri/target/release/bundle/appimage/*.AppImage.sig src-tauri/target/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}.AppImage.sig - mv src-tauri/target/release/bundle/rpm/*.rpm src-tauri/target/release/bundle/rpm/Qopy-${{ needs.prepare.outputs.version }}.rpm + mv src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb src-tauri/target/${{ matrix.target }}/release/bundle/deb/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.deb + mv src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage src-tauri/target/${{ matrix.target }}/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.AppImage + mv src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage.sig src-tauri/target/${{ matrix.target }}/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.AppImage.sig + mv src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm src-tauri/target/${{ matrix.target }}/release/bundle/rpm/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.rpm - uses: actions/upload-artifact@v4 with: - name: build-ubuntu-deb - path: src-tauri/target/release/bundle/deb/*.deb - - uses: actions/upload-artifact@v4 - with: - name: build-ubuntu-appimage - path: src-tauri/target/release/bundle/appimage/*.AppImage - - uses: actions/upload-artifact@v4 - with: - name: build-ubuntu-rpm - path: src-tauri/target/release/bundle/rpm/*.rpm - - uses: actions/upload-artifact@v4 - with: - name: updater-files-ubuntu + name: linux-${{ matrix.arch }}-binaries path: | - src-tauri/target/release/bundle/appimage/*.AppImage - src-tauri/target/release/bundle/appimage/*.AppImage.sig + src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb + src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage + src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage.sig + src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 21b6882..15f3d1e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -170,6 +170,13 @@ jobs: build-linux: permissions: write-all needs: prepare + strategy: + matrix: + include: + - target: "x86_64-unknown-linux-gnu" + arch: "x64" + - target: "aarch64-unknown-linux-gnu" + arch: "arm64" runs-on: ubuntu-latest env: TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} @@ -181,6 +188,8 @@ jobs: with: node-version: 20 - uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} - uses: swatinem/rust-cache@v2 with: workspaces: "src-tauri -> target" @@ -210,20 +219,20 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - args: --target x86_64-unknown-linux-gnu + args: --target ${{ matrix.target }} - 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 + mv src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb src-tauri/target/${{ matrix.target }}/release/bundle/deb/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.deb + mv src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage src-tauri/target/${{ matrix.target }}/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.AppImage + mv src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm src-tauri/target/${{ matrix.target }}/release/bundle/rpm/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.rpm - name: Upload artifacts uses: actions/upload-artifact@v4 with: - name: linux-binaries + name: linux-${{ matrix.arch }}-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 + src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb + src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage + src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm create-release: permissions: write-all @@ -250,19 +259,12 @@ jobs: 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" + DEBIAN_X64_HASH=$(sha256sum "artifacts/linux-x64-binaries/deb/Qopy-${VERSION}_x64.deb" | awk '{ print $1 }') + APPIMAGE_X64_HASH=$(sha256sum "artifacts/linux-x64-binaries/appimage/Qopy-${VERSION}_x64.AppImage" | awk '{ print $1 }') + RPM_X64_HASH=$(sha256sum "artifacts/linux-x64-binaries/rpm/Qopy-${VERSION}_x64.rpm" | awk '{ print $1 }') + DEBIAN_ARM64_HASH=$(sha256sum "artifacts/linux-arm64-binaries/deb/Qopy-${VERSION}_arm64.deb" | awk '{ print $1 }') + APPIMAGE_ARM64_HASH=$(sha256sum "artifacts/linux-arm64-binaries/appimage/Qopy-${VERSION}_arm64.AppImage" | awk '{ print $1 }') + RPM_ARM64_HASH=$(sha256sum "artifacts/linux-arm64-binaries/rpm/Qopy-${VERSION}_arm64.rpm" | awk '{ print $1 }') RELEASE_BODY=$(cat <<-EOF ## ♻️ Changelog @@ -275,9 +277,12 @@ jobs: - [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} + - [Debian (x64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_x64.deb) - ${DEBIAN_X64_HASH} + - [AppImage (x64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_x64.AppImage) - ${APPIMAGE_X64_HASH} + - [Red Hat (x64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_x64.rpm) - ${RPM_X64_HASH} + - [Debian (ARM64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_arm64.deb) - ${DEBIAN_ARM64_HASH} + - [AppImage (ARM64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_arm64.AppImage) - ${APPIMAGE_ARM64_HASH} + - [Red Hat (ARM64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_arm64.rpm) - ${RPM_ARM64_HASH} EOF ) From a3734eb9d6ee02d90485b5d7b454a48d814467ba Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Sun, 22 Dec 2024 00:07:58 +1000 Subject: [PATCH 003/110] chore: streamline artifact renaming and upload process in build and release workflows --- .github/workflows/build.yml | 53 +++++++++++++++-------------------- .github/workflows/release.yml | 53 ++++++++++++++++------------------- 2 files changed, 46 insertions(+), 60 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5d7aaa0..a7e7a7e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -151,36 +151,20 @@ jobs: - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: List Bundle Directory - shell: pwsh + - name: Rename and Publish Windows Artifacts 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 - } + 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 }}-binaries + name: build-windows-msi-${{ matrix.arch }} path: src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi + - uses: actions/upload-artifact@v4 + with: + name: updater-files-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 @@ -206,7 +190,7 @@ jobs: with: workspaces: "src-tauri -> target" cache-directories: "~/.cargo/registry/index/,~/.cargo/registry/cache/,~/.cargo/git/db/" - shared-key: "ubuntu-rust-cache" + shared-key: "linux-rust-cache" save-if: "true" - uses: actions/cache@v4 with: @@ -214,11 +198,20 @@ jobs: key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm- - - name: install dependencies + - name: Install dependencies run: | + sudo dpkg --add-architecture arm64 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 + if [ "${{ matrix.arch }}" = "arm64" ]; then + sudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu + sudo apt install -y libwebkit2gtk-4.1-dev:arm64 libssl-dev:arm64 libayatana-appindicator3-dev:arm64 librsvg2-dev:arm64 libasound2-dev:arm64 + fi + echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/lib/x86_64-linux-gnu/pkgconfig" >> $GITHUB_ENV + echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV + if [ "${{ matrix.arch }}" = "arm64" ]; then + echo "PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu" >> $GITHUB_ENV + fi - run: npm install -g pnpm && pnpm install - uses: tauri-apps/tauri-action@v0 env: @@ -229,7 +222,6 @@ jobs: run: | mv src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb src-tauri/target/${{ matrix.target }}/release/bundle/deb/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.deb mv src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage src-tauri/target/${{ matrix.target }}/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.AppImage - mv src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage.sig src-tauri/target/${{ matrix.target }}/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.AppImage.sig mv src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm src-tauri/target/${{ matrix.target }}/release/bundle/rpm/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.rpm - uses: actions/upload-artifact@v4 with: @@ -237,5 +229,4 @@ jobs: path: | src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage - src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage.sig src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 15f3d1e..21b6882 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -170,13 +170,6 @@ jobs: build-linux: permissions: write-all needs: prepare - strategy: - matrix: - include: - - target: "x86_64-unknown-linux-gnu" - arch: "x64" - - target: "aarch64-unknown-linux-gnu" - arch: "arm64" runs-on: ubuntu-latest env: TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} @@ -188,8 +181,6 @@ jobs: with: node-version: 20 - uses: dtolnay/rust-toolchain@stable - with: - targets: ${{ matrix.target }} - uses: swatinem/rust-cache@v2 with: workspaces: "src-tauri -> target" @@ -219,20 +210,20 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - args: --target ${{ matrix.target }} + args: --target x86_64-unknown-linux-gnu - name: Rename Linux Artifacts run: | - mv src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb src-tauri/target/${{ matrix.target }}/release/bundle/deb/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.deb - mv src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage src-tauri/target/${{ matrix.target }}/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.AppImage - mv src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm src-tauri/target/${{ matrix.target }}/release/bundle/rpm/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.rpm + 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-${{ matrix.arch }}-binaries + name: linux-binaries path: | - src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb - src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage - src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm + 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 @@ -259,12 +250,19 @@ jobs: 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_X64_HASH=$(sha256sum "artifacts/linux-x64-binaries/deb/Qopy-${VERSION}_x64.deb" | awk '{ print $1 }') - APPIMAGE_X64_HASH=$(sha256sum "artifacts/linux-x64-binaries/appimage/Qopy-${VERSION}_x64.AppImage" | awk '{ print $1 }') - RPM_X64_HASH=$(sha256sum "artifacts/linux-x64-binaries/rpm/Qopy-${VERSION}_x64.rpm" | awk '{ print $1 }') - DEBIAN_ARM64_HASH=$(sha256sum "artifacts/linux-arm64-binaries/deb/Qopy-${VERSION}_arm64.deb" | awk '{ print $1 }') - APPIMAGE_ARM64_HASH=$(sha256sum "artifacts/linux-arm64-binaries/appimage/Qopy-${VERSION}_arm64.AppImage" | awk '{ print $1 }') - RPM_ARM64_HASH=$(sha256sum "artifacts/linux-arm64-binaries/rpm/Qopy-${VERSION}_arm64.rpm" | 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 ## ♻️ Changelog @@ -277,12 +275,9 @@ jobs: - [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 (x64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_x64.deb) - ${DEBIAN_X64_HASH} - - [AppImage (x64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_x64.AppImage) - ${APPIMAGE_X64_HASH} - - [Red Hat (x64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_x64.rpm) - ${RPM_X64_HASH} - - [Debian (ARM64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_arm64.deb) - ${DEBIAN_ARM64_HASH} - - [AppImage (ARM64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_arm64.AppImage) - ${APPIMAGE_ARM64_HASH} - - [Red Hat (ARM64)](https://github.com/${{ github.repository }}/releases/download/v${VERSION}/Qopy-${VERSION}_arm64.rpm) - ${RPM_ARM64_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 ) From 93fb640ff2082ae05c94a09f90d677bbdb0e76cd Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Sun, 22 Dec 2024 00:12:01 +1000 Subject: [PATCH 004/110] chore: enhance ARM64 build workflow with additional dependencies and cross-compilation setup --- .github/workflows/build.yml | 53 +++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a7e7a7e..0091eb5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -202,16 +202,51 @@ jobs: run: | sudo dpkg --add-architecture arm64 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 + sudo apt install -y \ + libwebkit2gtk-4.1-dev \ + build-essential \ + curl \ + wget \ + file \ + libssl-dev \ + libayatana-appindicator3-dev \ + librsvg2-dev \ + libasound2-dev \ + rpm \ + pkg-config + if [ "${{ matrix.arch }}" = "arm64" ]; then - sudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu - sudo apt install -y libwebkit2gtk-4.1-dev:arm64 libssl-dev:arm64 libayatana-appindicator3-dev:arm64 librsvg2-dev:arm64 libasound2-dev:arm64 - fi - echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/lib/x86_64-linux-gnu/pkgconfig" >> $GITHUB_ENV - echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV - if [ "${{ matrix.arch }}" = "arm64" ]; then - echo "PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu" >> $GITHUB_ENV + sudo apt install -y \ + gcc-aarch64-linux-gnu \ + g++-aarch64-linux-gnu \ + libglib2.0-dev:arm64 \ + libwebkit2gtk-4.1-dev:arm64 \ + libssl-dev:arm64 \ + libayatana-appindicator3-dev:arm64 \ + librsvg2-dev:arm64 \ + libasound2-dev:arm64 \ + libgtk-3-dev:arm64 \ + libatk1.0-dev:arm64 \ + libgdk-pixbuf-2.0-dev:arm64 \ + libcairo2-dev:arm64 \ + libpango1.0-dev:arm64 \ + libsoup-3.0-dev:arm64 + + # Set up pkg-config for ARM64 + sudo mkdir -p /usr/lib/aarch64-linux-gnu/pkgconfig + sudo cp /usr/lib/x86_64-linux-gnu/pkgconfig/* /usr/lib/aarch64-linux-gnu/pkgconfig/ + + # Environment variables for cross-compilation + echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig" >> $GITHUB_ENV + echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV + echo "PKG_CONFIG_SYSROOT_DIR=/usr" >> $GITHUB_ENV + echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV + echo "CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc" >> $GITHUB_ENV + echo "CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++" >> $GITHUB_ENV + else + echo "PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig" >> $GITHUB_ENV fi + - run: npm install -g pnpm && pnpm install - uses: tauri-apps/tauri-action@v0 env: @@ -222,6 +257,7 @@ jobs: run: | mv src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb src-tauri/target/${{ matrix.target }}/release/bundle/deb/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.deb mv src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage src-tauri/target/${{ matrix.target }}/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.AppImage + mv src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage.sig src-tauri/target/${{ matrix.target }}/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.AppImage.sig mv src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm src-tauri/target/${{ matrix.target }}/release/bundle/rpm/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.rpm - uses: actions/upload-artifact@v4 with: @@ -229,4 +265,5 @@ jobs: path: | src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage + src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage.sig src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm From a0a9358f55559af75953f119477e54f9d2c4cd0d Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Sun, 22 Dec 2024 00:17:42 +1000 Subject: [PATCH 005/110] chore: optimize ARM64 build workflow by refining dependency installation and cross-compilation setup --- .github/workflows/build.yml | 56 +++++++------------------------------ 1 file changed, 10 insertions(+), 46 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0091eb5..ae76d7e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -162,7 +162,7 @@ jobs: - uses: actions/upload-artifact@v4 with: name: updater-files-windows-${{ matrix.arch }} - path: | + path: | src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi.sig @@ -190,7 +190,7 @@ jobs: with: workspaces: "src-tauri -> target" cache-directories: "~/.cargo/registry/index/,~/.cargo/registry/cache/,~/.cargo/git/db/" - shared-key: "linux-rust-cache" + shared-key: "ubuntu-rust-cache" save-if: "true" - uses: actions/cache@v4 with: @@ -202,51 +202,15 @@ jobs: run: | sudo dpkg --add-architecture arm64 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 \ - pkg-config - - if [ "${{ matrix.arch }}" = "arm64" ]; then - sudo apt install -y \ - gcc-aarch64-linux-gnu \ - g++-aarch64-linux-gnu \ - libglib2.0-dev:arm64 \ - libwebkit2gtk-4.1-dev:arm64 \ - libssl-dev:arm64 \ - libayatana-appindicator3-dev:arm64 \ - librsvg2-dev:arm64 \ - libasound2-dev:arm64 \ - libgtk-3-dev:arm64 \ - libatk1.0-dev:arm64 \ - libgdk-pixbuf-2.0-dev:arm64 \ - libcairo2-dev:arm64 \ - libpango1.0-dev:arm64 \ - libsoup-3.0-dev:arm64 - - # Set up pkg-config for ARM64 - sudo mkdir -p /usr/lib/aarch64-linux-gnu/pkgconfig - sudo cp /usr/lib/x86_64-linux-gnu/pkgconfig/* /usr/lib/aarch64-linux-gnu/pkgconfig/ - - # Environment variables for cross-compilation - echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig" >> $GITHUB_ENV - echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV - echo "PKG_CONFIG_SYSROOT_DIR=/usr" >> $GITHUB_ENV - echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV - echo "CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc" >> $GITHUB_ENV - echo "CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++" >> $GITHUB_ENV - else - echo "PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig" >> $GITHUB_ENV + sudo apt install -y libwebkit2gtk-4.1-dev build-essential curl wget file libssl-dev libayatana-appindicator3-dev librsvg2-dev libasound2-dev rpm + sudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu + # Install ARM64 dependencies + if [ "${{ matrix.target }}" = "aarch64-unknown-linux-gnu" ]; then + sudo apt install -y libwebkit2gtk-4.1-dev:arm64 libssl-dev:arm64 libayatana-appindicator3-dev:arm64 librsvg2-dev:arm64 libasound2-dev:arm64 fi - + echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV + echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig" >> $GITHUB_ENV + echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV - run: npm install -g pnpm && pnpm install - uses: tauri-apps/tauri-action@v0 env: From d4d15f085a72284852071105eec9bf30e84d97b9 Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Sun, 22 Dec 2024 11:12:44 +1000 Subject: [PATCH 006/110] chore: enhance Windows build workflow with improved artifact listing and renaming process --- .github/workflows/build.yml | 67 ++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ae76d7e..9f5c162 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -151,17 +151,48 @@ jobs: - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Rename and Publish Windows Artifacts + - name: List Build Directories + shell: pwsh 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 + 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 Windows Artifacts + shell: pwsh + run: | + $targetPath = "src-tauri/target/${{ matrix.target }}/release/bundle/msi" + $version = "${{ needs.prepare.outputs.version }}" + $arch = "${{ matrix.arch }}" + + Write-Output "Looking for MSI files in: $targetPath" + + if (!(Test-Path $targetPath)) { + Write-Error "Target path does not exist: $targetPath" + Write-Output "Available directories:" + Get-ChildItem -Path "src-tauri/target" -Recurse -Directory | Format-Table -Property FullName + exit 1 + } + + $msiFiles = Get-ChildItem -Path "$targetPath/*.msi" -ErrorAction SilentlyContinue + if ($null -eq $msiFiles) { + Write-Error "No MSI files found in: $targetPath" + exit 1 + } + + foreach ($file in $msiFiles) { + $newName = "Qopy-${version}_${arch}.msi" + Write-Output "Renaming $($file.Name) to $newName" + Rename-Item -Path $file.FullName -NewName $newName -ErrorAction Stop + } + - uses: actions/upload-artifact@v4 with: - name: build-windows-msi-${{ matrix.arch }} - path: src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi - - uses: actions/upload-artifact@v4 - with: - name: updater-files-windows-${{ matrix.arch }} + name: windows-${{ matrix.arch }}-binaries path: | src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi.sig @@ -201,16 +232,26 @@ jobs: - name: Install dependencies run: | sudo dpkg --add-architecture arm64 + # Update sources.list to use jammy (22.04) + sudo sed -i 's/noble/jammy/g' /etc/apt/sources.list 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 sudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu - # Install ARM64 dependencies + if [ "${{ matrix.target }}" = "aarch64-unknown-linux-gnu" ]; then - sudo apt install -y libwebkit2gtk-4.1-dev:arm64 libssl-dev:arm64 libayatana-appindicator3-dev:arm64 librsvg2-dev:arm64 libasound2-dev:arm64 + # Install ARM64 dependencies from jammy + sudo apt install -y \ + libwebkit2gtk-4.1-dev:arm64 \ + libssl-dev:arm64 \ + libayatana-appindicator3-dev:arm64 \ + librsvg2-dev:arm64 \ + libasound2-dev:arm64 + + # Set up cross-compilation environment + echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV + echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig" >> $GITHUB_ENV + echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV fi - echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV - echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig" >> $GITHUB_ENV - echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV - run: npm install -g pnpm && pnpm install - uses: tauri-apps/tauri-action@v0 env: From b706207aafbfa7a3287638f3982d50b292d4f7db Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Sun, 22 Dec 2024 12:51:46 +1000 Subject: [PATCH 007/110] chore: refine Windows and Linux build workflows with improved artifact listing and renaming --- .github/workflows/build.yml | 80 ++++++++++--------------------------- 1 file changed, 22 insertions(+), 58 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9f5c162..7adbe1e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -151,7 +151,9 @@ jobs: - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: List Build Directories + with: + args: ${{ matrix.args }} + - name: List Bundle Directory shell: pwsh run: | Write-Output "Checking build directories..." @@ -161,51 +163,31 @@ jobs: Write-Output "Found MSI file: $($_.FullName)" } } - - name: Rename Windows Artifacts shell: pwsh run: | - $targetPath = "src-tauri/target/${{ matrix.target }}/release/bundle/msi" $version = "${{ needs.prepare.outputs.version }}" $arch = "${{ matrix.arch }}" - Write-Output "Looking for MSI files in: $targetPath" - - if (!(Test-Path $targetPath)) { - Write-Error "Target path does not exist: $targetPath" - Write-Output "Available directories:" - Get-ChildItem -Path "src-tauri/target" -Recurse -Directory | Format-Table -Property FullName - exit 1 - } - - $msiFiles = Get-ChildItem -Path "$targetPath/*.msi" -ErrorAction SilentlyContinue - if ($null -eq $msiFiles) { - Write-Error "No MSI files found in: $targetPath" - exit 1 - } + # Find MSI files recursively + $msiFiles = Get-ChildItem -Path "src-tauri/target" -Recurse -Filter "*.msi" foreach ($file in $msiFiles) { $newName = "Qopy-${version}_${arch}.msi" Write-Output "Renaming $($file.Name) to $newName" - Rename-Item -Path $file.FullName -NewName $newName -ErrorAction Stop + Rename-Item -Path $file.FullName -NewName $newName + $newPath = Join-Path $file.Directory.FullName $newName + Write-Output "New file path: $newPath" } - - uses: actions/upload-artifact@v4 with: name: windows-${{ matrix.arch }}-binaries path: | - src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi - src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi.sig + src-tauri/target/**/release/bundle/msi/*.msi + src-tauri/target/**/release/bundle/msi/*.msi.sig build-ubuntu: needs: prepare - strategy: - matrix: - include: - - target: "x86_64-unknown-linux-gnu" - arch: "x64" - - target: "aarch64-unknown-linux-gnu" - arch: "arm64" runs-on: ubuntu-latest env: TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} @@ -216,7 +198,7 @@ jobs: node-version: 20 - uses: dtolnay/rust-toolchain@stable with: - targets: ${{ matrix.target }} + targets: x86_64-unknown-linux-gnu - uses: swatinem/rust-cache@v2 with: workspaces: "src-tauri -> target" @@ -231,44 +213,26 @@ jobs: ${{ runner.os }}-pnpm- - name: Install dependencies run: | - sudo dpkg --add-architecture arm64 - # Update sources.list to use jammy (22.04) - sudo sed -i 's/noble/jammy/g' /etc/apt/sources.list 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 - sudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu - - if [ "${{ matrix.target }}" = "aarch64-unknown-linux-gnu" ]; then - # Install ARM64 dependencies from jammy - sudo apt install -y \ - libwebkit2gtk-4.1-dev:arm64 \ - libssl-dev:arm64 \ - libayatana-appindicator3-dev:arm64 \ - librsvg2-dev:arm64 \ - libasound2-dev:arm64 - - # Set up cross-compilation environment - echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV - echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig" >> $GITHUB_ENV - echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV - fi + 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 ${{ matrix.target }} + args: --target x86_64-unknown-linux-gnu - name: Rename Linux Artifacts run: | - mv src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb src-tauri/target/${{ matrix.target }}/release/bundle/deb/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.deb - mv src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage src-tauri/target/${{ matrix.target }}/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.AppImage - mv src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage.sig src-tauri/target/${{ matrix.target }}/release/bundle/appimage/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.AppImage.sig - mv src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm src-tauri/target/${{ matrix.target }}/release/bundle/rpm/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.rpm + 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: linux-${{ matrix.arch }}-binaries + name: linux-x64-binaries path: | - src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb - src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage - src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage.sig - src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm + 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/appimage/*.AppImage.sig + src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/*.rpm From 66f229be7e4a117d5aea388f8d522289f11f0a3c Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Sun, 22 Dec 2024 17:10:24 +1000 Subject: [PATCH 008/110] chore: improve artifact naming and organization in build workflows for macOS, Windows, and Ubuntu --- .github/workflows/build.yml | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7adbe1e..85e4c27 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -104,11 +104,11 @@ jobs: mv src-tauri/target/${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }}/release/bundle/macos/*.app.tar.gz.sig src-tauri/target/${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }}/release/bundle/macos/Qopy-${{ needs.prepare.outputs.version }}_${{ matrix.arch }}.app.tar.gz.sig - uses: actions/upload-artifact@v4 with: - name: build-macos-dmg-${{ matrix.arch }} + name: macos-dmg-${{ matrix.arch }} path: src-tauri/target/${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }}/release/bundle/dmg/*.dmg - uses: actions/upload-artifact@v4 with: - name: updater-files-macos-${{ matrix.arch }} + name: updater-macos-${{ matrix.arch }} path: | src-tauri/target/${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }}/release/bundle/macos/*.app.tar.gz src-tauri/target/${{ matrix.args == '--target aarch64-apple-darwin' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin' }}/release/bundle/macos/*.app.tar.gz.sig @@ -181,10 +181,16 @@ jobs: } - uses: actions/upload-artifact@v4 with: - name: windows-${{ matrix.arch }}-binaries + name: windows-${{ matrix.arch }} path: | src-tauri/target/**/release/bundle/msi/*.msi src-tauri/target/**/release/bundle/msi/*.msi.sig + - uses: actions/upload-artifact@v4 + with: + name: updater-windows-${{ matrix.arch }} + path: | + src-tauri/target/${{ matrix.target }}/release/Qopy.msi + src-tauri/target/${{ matrix.target }}/release/Qopy.msi.sig build-ubuntu: needs: prepare @@ -230,9 +236,19 @@ jobs: 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: linux-x64-binaries + name: ubuntu-deb + path: src-tauri/target/release/bundle/deb/*.deb + - uses: actions/upload-artifact@v4 + with: + name: ubuntu-appimage + path: src-tauri/target/release/bundle/appimage/*.AppImage + - uses: actions/upload-artifact@v4 + with: + name: ubuntu-rpm + path: src-tauri/target/release/bundle/rpm/*.rpm + - uses: actions/upload-artifact@v4 + with: + name: updater-files-ubuntu 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/appimage/*.AppImage.sig - src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/*.rpm + src-tauri/target/release/bundle/appimage/*.AppImage + src-tauri/target/release/bundle/appimage/*.AppImage.sig \ No newline at end of file From 3824f24be4c9e0934ea2c096733589d7da102fc0 Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Sun, 22 Dec 2024 17:49:08 +1000 Subject: [PATCH 009/110] chore: update Windows and Ubuntu build workflows for improved artifact renaming and organization --- .github/workflows/build.yml | 38 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 85e4c27..4c23943 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -163,34 +163,20 @@ jobs: Write-Output "Found MSI file: $($_.FullName)" } } - - name: Rename Windows Artifacts - shell: pwsh + - name: Rename and Publish Windows Artifacts run: | - $version = "${{ needs.prepare.outputs.version }}" - $arch = "${{ matrix.arch }}" - - # Find MSI files recursively - $msiFiles = Get-ChildItem -Path "src-tauri/target" -Recurse -Filter "*.msi" - - foreach ($file in $msiFiles) { - $newName = "Qopy-${version}_${arch}.msi" - Write-Output "Renaming $($file.Name) to $newName" - Rename-Item -Path $file.FullName -NewName $newName - $newPath = Join-Path $file.Directory.FullName $newName - Write-Output "New file path: $newPath" - } + 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/**/release/bundle/msi/*.msi - src-tauri/target/**/release/bundle/msi/*.msi.sig + 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/Qopy.msi - src-tauri/target/${{ matrix.target }}/release/Qopy.msi.sig + src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi + src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi.sig build-ubuntu: needs: prepare @@ -237,18 +223,18 @@ jobs: - uses: actions/upload-artifact@v4 with: name: ubuntu-deb - path: src-tauri/target/release/bundle/deb/*.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/release/bundle/appimage/*.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/release/bundle/rpm/*.rpm + path: src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/rpm/*.rpm - uses: actions/upload-artifact@v4 with: - name: updater-files-ubuntu + name: updater-ubuntu path: | - src-tauri/target/release/bundle/appimage/*.AppImage - src-tauri/target/release/bundle/appimage/*.AppImage.sig \ No newline at end of file + 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 From f44be512fe09b7acad3ec6ab669a3a44e72a28b4 Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Mon, 23 Dec 2024 14:34:21 +1000 Subject: [PATCH 010/110] feat: integrate event tracking for hotkey actions, history management, and settings updates --- src-tauri/Cargo.lock | 40 ++++++++++++++++++++++++-- src-tauri/Cargo.toml | 5 ++-- src-tauri/src/api/clipboard.rs | 51 ++++++++++++++++++++++------------ src-tauri/src/api/hotkeys.rs | 5 ++++ src-tauri/src/api/tray.rs | 23 ++++++++++----- src-tauri/src/db/history.rs | 16 ++++++++++- src-tauri/src/db/settings.rs | 24 ++++++++++++---- src-tauri/src/main.rs | 21 +++++++++++++- 8 files changed, 149 insertions(+), 36 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 675d1c5..43ff881 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1643,6 +1643,21 @@ dependencies = [ "new_debug_unreachable", ] +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.30" @@ -1729,6 +1744,7 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -4081,6 +4097,7 @@ dependencies = [ "sqlx", "tauri", "tauri-build", + "tauri-plugin-aptabase", "tauri-plugin-autostart", "tauri-plugin-clipboard", "tauri-plugin-dialog", @@ -4796,9 +4813,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "itoa 1.0.11", "memchr", @@ -5664,6 +5681,25 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tauri-plugin-aptabase" +version = "0.5.1" +source = "git+https://github.com/aptabase/tauri-plugin-aptabase?branch=v2#373abe1954bf20152082e506d36be07727259bb5" +dependencies = [ + "futures", + "log", + "os_info", + "rand 0.8.5", + "reqwest", + "serde", + "serde_json", + "sys-locale", + "tauri", + "tauri-plugin", + "time", + "tokio", +] + [[package]] name = "tauri-plugin-autostart" version = "2.2.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9710029..d151155 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -13,7 +13,7 @@ tauri-build = { version = "2.0.3", features = [] } tauri = { version = "2.1.1", features = [ "macos-private-api", "tray-icon", - "image-png", + "image-png" ] } tauri-plugin-sql = { version = "2.2.0", features = ["sqlite"] } tauri-plugin-autostart = "2.2.0" @@ -24,10 +24,11 @@ tauri-plugin-fs = "2.2.0" tauri-plugin-clipboard = "2.1.11" tauri-plugin-prevent-default = "1.0.1" tauri-plugin-global-shortcut = "2.2.0" +tauri-plugin-aptabase = { git = "https://github.com/aptabase/tauri-plugin-aptabase", branch = "v2" } sqlx = { version = "0.8.2", features = ["runtime-tokio-native-tls", "sqlite", "chrono"] } serde = { version = "1.0.216", features = ["derive"] } tokio = { version = "1.42.0", features = ["full"] } -serde_json = "1.0.133" +serde_json = "1.0.134" rdev = "0.5.3" rand = "0.8.5" base64 = "0.22.1" diff --git a/src-tauri/src/api/clipboard.rs b/src-tauri/src/api/clipboard.rs index 76f245f..59ac7b1 100644 --- a/src-tauri/src/api/clipboard.rs +++ b/src-tauri/src/api/clipboard.rs @@ -1,3 +1,4 @@ +use tauri_plugin_aptabase::EventTracker; use base64::{engine::general_purpose::STANDARD, Engine}; // use hyperpolyglot; use lazy_static::lazy_static; @@ -7,7 +8,7 @@ use sqlx::SqlitePool; use std::fs; use std::sync::atomic::{AtomicBool, Ordering}; use std::{thread, time::Duration}; -use tauri::{AppHandle, Emitter, Listener, Manager, Runtime}; +use tauri::{AppHandle, Emitter, Listener, Manager}; use tauri_plugin_clipboard::Clipboard; use tokio::runtime::Runtime as TokioRuntime; use url::Url; @@ -23,8 +24,8 @@ lazy_static! { } #[tauri::command] -pub async fn write_and_paste( - app_handle: tauri::AppHandle, +pub async fn write_and_paste( + app_handle: AppHandle, content: String, content_type: String, ) -> Result<(), String> { @@ -80,39 +81,44 @@ pub async fn write_and_paste( 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 = app.clone(); +pub fn setup(app: &AppHandle) { + let app_handle = app.clone(); let runtime = TokioRuntime::new().expect("Failed to create Tokio runtime"); - app.clone().listen( + app_handle.clone().listen( "plugin:clipboard://clipboard-monitor/update", move |_event| { - let app = app.clone(); + let app_handle = app_handle.clone(); runtime.block_on(async move { if IS_PROGRAMMATIC_PASTE.load(Ordering::SeqCst) { return; } - let clipboard = app.state::(); + let clipboard = app_handle.state::(); let available_types = clipboard.available_types().unwrap(); let (app_name, app_icon) = get_app_info(); - match get_pool(&app).await { + 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, &image_data) + 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), + HistoryItem::new(app_name, ContentType::Image, file_path, None, app_icon, None) ).await; } } else if available_types.files { @@ -120,6 +126,7 @@ pub fn setup(app: &AppHandle) { 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(), @@ -135,6 +142,7 @@ pub fn setup(app: &AppHandle) { } 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) { @@ -145,6 +153,7 @@ pub fn setup(app: &AppHandle) { }; let _ = db::history::add_history_item( + app_handle.clone(), pool, HistoryItem::new(app_name, ContentType::Link, text, favicon, app_icon, None) ).await; @@ -167,13 +176,15 @@ pub fn setup(app: &AppHandle) { ).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, None, app_icon, None) + HistoryItem::new(app_name, ContentType::Text, text.clone(), None, app_icon, None) ).await; } } @@ -187,14 +198,20 @@ pub fn setup(app: &AppHandle) { } } - let _ = app.emit("clipboard-content-updated", ()); + 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, +async fn get_pool( + app_handle: &AppHandle, ) -> Result, Box> { Ok(app_handle.state::()) } @@ -211,8 +228,8 @@ pub fn start_monitor(app_handle: AppHandle) -> Result<(), String> { Ok(()) } -async fn save_image_to_file( - app_handle: &AppHandle, +async fn save_image_to_file( + app_handle: &AppHandle, base64_data: &str, ) -> Result> { let app_data_dir = app_handle.path().app_data_dir().unwrap(); diff --git a/src-tauri/src/api/hotkeys.rs b/src-tauri/src/api/hotkeys.rs index 7a0b015..0470e24 100644 --- a/src-tauri/src/api/hotkeys.rs +++ b/src-tauri/src/api/hotkeys.rs @@ -1,3 +1,4 @@ +use tauri_plugin_aptabase::EventTracker; use crate::utils::commands::center_window_on_current_monitor; use global_hotkey::{ hotkey::{Code, HotKey, Modifiers}, @@ -142,4 +143,8 @@ fn handle_hotkey_event(app_handle: &AppHandle) { 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" } + }))); } diff --git a/src-tauri/src/api/tray.rs b/src-tauri/src/api/tray.rs index 82dd843..8c3d9bc 100644 --- a/src-tauri/src/api/tray.rs +++ b/src-tauri/src/api/tray.rs @@ -3,10 +3,14 @@ use tauri::{ 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 window_clone_for_tray = window.clone(); + 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(); @@ -24,20 +28,25 @@ pub fn setup(app: &mut tauri::App) -> Result<(), Box> { ) .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 is_visible = window_clone_for_tray.is_visible().unwrap(); + 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_clone_for_tray.hide().unwrap(); + window.hide().unwrap(); } else { - window_clone_for_tray.show().unwrap(); - window_clone_for_tray.set_focus().unwrap(); + window.show().unwrap(); + window.set_focus().unwrap(); } - window_clone_for_tray.emit("main_route", ()).unwrap(); + window.emit("main_route", ()).unwrap(); } "keybind" => { - window_clone_for_tray.emit("change_keybind", ()).unwrap(); + let _ = _app.track_event("tray_keybind_change", None); + window.emit("change_keybind", ()).unwrap(); } _ => (), }) diff --git a/src-tauri/src/db/history.rs b/src-tauri/src/db/history.rs index fc24bcb..5296a79 100644 --- a/src-tauri/src/db/history.rs +++ b/src-tauri/src/db/history.rs @@ -4,6 +4,7 @@ use rand::distributions::Alphanumeric; use rand::{thread_rng, Rng}; use sqlx::{Row, SqlitePool}; use std::fs; +use tauri_plugin_aptabase::EventTracker; pub async fn initialize_history(pool: &SqlitePool) -> Result<(), Box> { let id: String = thread_rng() @@ -53,6 +54,7 @@ pub async fn get_history(pool: tauri::State<'_, SqlitePool>) -> Result, item: HistoryItem, ) -> Result<(), String> { @@ -95,6 +97,10 @@ pub async fn add_history_item( } } + let _ = app_handle.track_event("history_item_added", Some(serde_json::json!({ + "content_type": item.content_type.to_string() + }))); + Ok(()) } @@ -163,6 +169,7 @@ pub async fn load_history_chunk( #[tauri::command] pub async fn delete_history_item( + app_handle: tauri::AppHandle, pool: tauri::State<'_, SqlitePool>, id: String, ) -> Result<(), String> { @@ -172,16 +179,23 @@ pub async fn delete_history_item( .await .map_err(|e| e.to_string())?; + let _ = app_handle.track_event("history_item_deleted", None); + Ok(()) } #[tauri::command] -pub async fn clear_history(pool: tauri::State<'_, SqlitePool>) -> Result<(), String> { +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(()) } diff --git a/src-tauri/src/db/settings.rs b/src-tauri/src/db/settings.rs index 406bee0..bdd6f58 100644 --- a/src-tauri/src/db/settings.rs +++ b/src-tauri/src/db/settings.rs @@ -3,6 +3,7 @@ use serde_json; use sqlx::Row; use sqlx::SqlitePool; use tauri::{Emitter, Manager}; +use tauri_plugin_aptabase::EventTracker; #[derive(Deserialize, Serialize)] struct KeybindSetting { @@ -26,9 +27,16 @@ pub async fn initialize_settings(pool: &SqlitePool) -> Result<(), Box, pool: tauri::State<'_, SqlitePool>, + keybind: Vec, ) -> Result<(), String> { + let keybind_str = keybind.join("+"); + let keybind_clone = keybind_str.clone(); + + app_handle + .emit("update-shortcut", &keybind_str) + .map_err(|e| e.to_string())?; + let json = serde_json::to_string(&keybind).map_err(|e| e.to_string())?; sqlx::query("INSERT OR REPLACE INTO settings (key, value) VALUES ('keybind', ?)") @@ -37,10 +45,9 @@ pub async fn save_keybind( .await .map_err(|e| e.to_string())?; - let keybind_str = keybind.join("+"); - app_handle - .emit("update-shortcut", keybind_str) - .map_err(|e| e.to_string())?; + let _ = app_handle.track_event("keybind_saved", Some(serde_json::json!({ + "keybind": keybind_clone + }))); Ok(()) } @@ -61,17 +68,22 @@ pub async fn get_setting( #[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) + .bind(key.clone()) .bind(value) .execute(&*pool) .await .map_err(|e| e.to_string())?; + let _ = app_handle.track_event("setting_saved", Some(serde_json::json!({ + "key": key + }))); + Ok(()) } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 0621936..c6aed37 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -7,15 +7,19 @@ mod api; mod db; mod utils; -use sqlx::sqlite::SqlitePoolOptions; use std::fs; use tauri::Manager; use tauri::WebviewUrl; use tauri::WebviewWindow; +use sqlx::sqlite::SqlitePoolOptions; use tauri_plugin_autostart::MacosLauncher; use tauri_plugin_prevent_default::Flags; +use tauri_plugin_aptabase::{EventTracker, InitOptions}; 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()) @@ -23,6 +27,19 @@ fn main() { .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![]), @@ -85,6 +102,8 @@ fn main() { utils::commands::center_window_on_current_monitor(&main_window); main_window.hide()?; + let _ = app.track_event("app_started", None); + tauri::async_runtime::spawn(async move { api::updater::check_for_updates(app_handle).await; }); From 39d41e8f106f2aa39598d45b294798b619c63e2b Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Mon, 23 Dec 2024 15:09:57 +1000 Subject: [PATCH 011/110] chore: bump version of qopy to 0.3.1 in Cargo files and configuration --- src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 43ff881..d24fd5b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4075,7 +4075,7 @@ dependencies = [ [[package]] name = "qopy" -version = "0.3.0" +version = "0.3.1" dependencies = [ "active-win-pos-rs", "applications", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index d151155..6045afb 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "qopy" -version = "0.3.0" +version = "0.3.1" description = "Qopy" authors = ["pandadev"] edition = "2021" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 46e178a..dd53dd9 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,6 +1,6 @@ { "productName": "Qopy", - "version": "0.3.0", + "version": "0.3.1", "identifier": "net.pandadev.qopy", "build": { "frontendDist": "../dist", From 437cd2b3e84ab5cca56a441866aaf0a945475932 Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Mon, 23 Dec 2024 20:07:36 +1000 Subject: [PATCH 012/110] docs(readme): update download links at the top --- README.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 11608fe..658482e 100644 --- a/README.md +++ b/README.md @@ -10,22 +10,27 @@ The fixed and simple clipboard manager for both Windows and Linux. Download for - - Windows + + Windows (x64) - + + Windows (arm64) + + + + macOS (Silicon) - + macOS (Intel) - + Linux From c484b67edb737d5b347976e4cdbc5cf81f539ea0 Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Mon, 23 Dec 2024 20:19:19 +1000 Subject: [PATCH 013/110] feat(readme): download section redesign --- README.md | 62 ++++++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 658482e..c13d915 100644 --- a/README.md +++ b/README.md @@ -5,39 +5,35 @@ The fixed and simple clipboard manager for both Windows and Linux. - - - - - - - - - - - -
Download for - - Windows (x64) - - - - Windows (arm64) - - - - macOS (Silicon) - - - - macOS (Intel) - - - - Linux - -
- + + Windows (x64) + +• + + Windows (arm64) + +
+ + Linux (deb) + +• + + Linux (rpm) + +• + + Linux (AppImage) + +
+ + macOS (Silicon) + +• + + macOS (Intel) + +
+
Nightly releases can be found here From 5bcc084833a27ca3a3bd89cc43333663523d59aa Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Tue, 24 Dec 2024 23:29:46 +1000 Subject: [PATCH 014/110] docs(readme): update download links to version 0.3.1 --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c13d915..7d75f63 100644 --- a/README.md +++ b/README.md @@ -5,31 +5,31 @@ 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)
From a4657448e6dcbaad02089a7a8de7ad961a58f7bd Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Wed, 25 Dec 2024 17:17:59 +1000 Subject: [PATCH 015/110] docs(readme): roadmap update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7d75f63..452991a 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Qopy is a fixed clipboard manager designed as a simple alternative to the standa - [ ] [Setup guide](https://github.com/0PandaDEV/Qopy/blob/main/GET_STARTED.md) - [ ] Sync Clipboard across devices https://github.com/0PandaDEV/Qopy/issues/8 - [ ] Settings https://github.com/0PandaDEV/Qopy/issues/2 -- [ ] Metadata for copied items https://github.com/0PandaDEV/Qopy/issues/5 +- [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 From fc0c52228c042f5e3cbe8aa3ea8d8c5a8a12e73f Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Wed, 25 Dec 2024 18:14:14 +1000 Subject: [PATCH 016/110] chore: update nuxt version to 3.15.0 in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5e1944c..aad552e 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "@tauri-apps/cli": "2.1.0", "@tauri-apps/plugin-autostart": "2.2.0", "@tauri-apps/plugin-os": "2.2.0", - "nuxt": "3.14.1592", + "nuxt": "3.15.0", "overlayscrollbars": "2.10.1", "overlayscrollbars-vue": "0.5.9", "sass-embedded": "1.83.0", From f59c5bbc959f24b84c7b897c1dceb51be0ce0608 Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Wed, 25 Dec 2024 20:33:09 +1000 Subject: [PATCH 017/110] fix: windows ui bugs #21 --- app.vue | 2 ++ assets/css/index.scss | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app.vue b/app.vue index ef6e0aa..8f75e44 100644 --- a/app.vue +++ b/app.vue @@ -69,6 +69,8 @@ html, body, #__nuxt { background-color: transparent; + width: 750px; + height: 474px; } .os-scrollbar-horizontal { diff --git a/assets/css/index.scss b/assets/css/index.scss index db473f6..63ae190 100644 --- a/assets/css/index.scss +++ b/assets/css/index.scss @@ -7,8 +7,8 @@ $text2: #ada9a1; $mutedtext: #78756f; .bg { - width: 750px; - height: 474px; + width: 100%; + height: 100%; background-color: $primary; border: 1px solid $divider; border-radius: 12px; From 4adb57d6adb0f3dc747889ebb9ccea5c86a5596f Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Wed, 25 Dec 2024 20:34:57 +1000 Subject: [PATCH 018/110] fix: font no displayed in content --- assets/css/index.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/css/index.scss b/assets/css/index.scss index 63ae190..2fb355a 100644 --- a/assets/css/index.scss +++ b/assets/css/index.scss @@ -99,7 +99,7 @@ $mutedtext: #78756f; top: 53px; left: 284px; height: calc(100vh - 254px); - font-family: CommitMono Nerd Font !important; + font-family: CommitMono !important; font-size: 12px; letter-spacing: 1; border-radius: 10px; @@ -116,7 +116,7 @@ $mutedtext: #78756f; } span { - font-family: CommitMono Nerd Font !important; + font-family: CommitMono !important; } .image { From a0cbd13f53819beac2de47371a38bc168061f52c Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Wed, 25 Dec 2024 20:36:47 +1000 Subject: [PATCH 019/110] chore: update qopy version to 0.3.2 in Cargo files --- src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index d24fd5b..7004a95 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4075,7 +4075,7 @@ dependencies = [ [[package]] name = "qopy" -version = "0.3.1" +version = "0.3.2" dependencies = [ "active-win-pos-rs", "applications", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 6045afb..d6df90d 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "qopy" -version = "0.3.1" +version = "0.3.2" description = "Qopy" authors = ["pandadev"] edition = "2021" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index dd53dd9..daf875d 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,6 +1,6 @@ { "productName": "Qopy", - "version": "0.3.1", + "version": "0.3.2", "identifier": "net.pandadev.qopy", "build": { "frontendDist": "../dist", From 18ca53ef04c132bf5f98b51692c2077870c0d4bd Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Wed, 25 Dec 2024 21:14:55 +1000 Subject: [PATCH 020/110] feat(logger): enhance logging format and add panic hook --- src-tauri/src/utils/logger.rs | 46 +++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/src-tauri/src/utils/logger.rs b/src-tauri/src/utils/logger.rs index d2f1442..114b2c6 100644 --- a/src-tauri/src/utils/logger.rs +++ b/src-tauri/src/utils/logger.rs @@ -2,6 +2,7 @@ use chrono; use log::{LevelFilter, SetLoggerError}; use std::fs::{File, OpenOptions}; use std::io::Write; +use std::panic; pub struct FileLogger { file: File, @@ -15,14 +16,18 @@ impl log::Log for FileLogger { fn log(&self, record: &log::Record) { if self.enabled(record.metadata()) { let mut file = self.file.try_clone().expect("Failed to clone file handle"); + + // Format: timestamp [LEVEL] target: message (file:line) writeln!( file, - "{} - {}: {}", + "{} [{:<5}] {}: {} ({}:{})", chrono::Local::now().format("%Y-%m-%d %H:%M:%S"), record.level(), - record.args() - ) - .expect("Failed to write to log file"); + record.target(), + record.args(), + record.file().unwrap_or("unknown"), + record.line().unwrap_or(0) + ).expect("Failed to write to log file"); } } @@ -35,15 +40,42 @@ 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"); + // Use .log extension for standard log files let log_path = logs_dir.join("app.log"); let file = OpenOptions::new() .create(true) - .append(true) - .open(log_path) + .append(true) // Use append mode instead of write + .open(&log_path) .expect("Failed to open log file"); + // Set up panic hook + 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(()) -} +} \ No newline at end of file From dc34912895a3218cadee91567e6d59a54c9d9444 Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Wed, 25 Dec 2024 21:16:23 +1000 Subject: [PATCH 021/110] fix(release): improve changelog generation and add debug information --- .github/workflows/release.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 21b6882..5b6ecf8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -243,7 +243,14 @@ jobs: id: release_body run: | VERSION="${{ needs.prepare.outputs.version }}" - CHANGES=$(git log $(git describe --tags --abbrev=0)..HEAD --pretty=format:"- %s") + echo "Debug: Listing tags" + git tag -l + echo "Debug: Getting latest tag" + git describe --tags --abbrev=0 || echo "No tags found" + echo "Debug: Generating changelog" + CHANGES=$(git log "$(git describe --tags --abbrev=0 2>/dev/null || echo HEAD^)" HEAD --pretty=format:"- %s" || echo "No changelog available") + echo "Debug: Changelog content:" + echo "$CHANGES" # Calculate hashes with corrected paths WINDOWS_ARM_HASH=$(sha256sum "artifacts/windows-arm64-binaries/Qopy-${VERSION}_arm64.msi" | awk '{ print $1 }') From 1417d35cd7ee4a94a9319846c843ee3d7e4e3d9c Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Wed, 25 Dec 2024 21:31:26 +1000 Subject: [PATCH 022/110] fix(release): enhance changelog generation to handle missing tags --- .github/workflows/release.yml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5b6ecf8..f79b85d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -243,12 +243,18 @@ jobs: id: release_body run: | VERSION="${{ needs.prepare.outputs.version }}" - echo "Debug: Listing tags" - git tag -l - echo "Debug: Getting latest tag" - git describe --tags --abbrev=0 || echo "No tags found" - echo "Debug: Generating changelog" - CHANGES=$(git log "$(git describe --tags --abbrev=0 2>/dev/null || echo HEAD^)" HEAD --pretty=format:"- %s" || echo "No changelog available") + + # Get the most recent release tag (v* tags only) + LAST_TAG=$(git describe --match "v*" --abbrev=0 --tags `git rev-list --tags --skip=1 --max-count=1` 2>/dev/null || echo "") + + if [ -n "$LAST_TAG" ]; then + echo "Debug: Found last release tag: $LAST_TAG" + CHANGES=$(git log ${LAST_TAG}..HEAD --pretty=format:"- %s") + else + echo "Debug: No previous release tag found, using first commit" + CHANGES=$(git log --pretty=format:"- %s") + fi + echo "Debug: Changelog content:" echo "$CHANGES" From 2fa82d758429f8fd7595f0a4cb9bd2aa0e8c2deb Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Wed, 25 Dec 2024 23:44:06 +1000 Subject: [PATCH 023/110] fix: interface unusable becasue no interaction was possible --- app.vue | 9 ++++++--- components/Noise.vue | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app.vue b/app.vue index 8f75e44..2d69efc 100644 --- a/app.vue +++ b/app.vue @@ -1,5 +1,5 @@ @@ -59,6 +59,8 @@ onMounted(async () => { scroll-behavior: smooth; scrollbar-width: thin; user-select: none; + position: relative; + z-index: 1; --os-handle-bg: #ADA9A1; --os-handle-bg-hover: #78756F; @@ -66,11 +68,12 @@ onMounted(async () => { } html, -body, -#__nuxt { +body { background-color: transparent; width: 750px; height: 474px; + user-select: none !important; + pointer-events: none !important; } .os-scrollbar-horizontal { diff --git a/components/Noise.vue b/components/Noise.vue index 41bb879..67fcbff 100644 --- a/components/Noise.vue +++ b/components/Noise.vue @@ -12,7 +12,7 @@ height: 100vh; pointer-events: none; user-select: none; - z-index: 0; + z-index: -1; background-image: url('/noise.png'); background-repeat: repeat; image-rendering: pixelated; From 1a15ea777779327acf0bf8a09edd8e8180ea774e Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Thu, 26 Dec 2024 00:17:25 +1000 Subject: [PATCH 024/110] chore: update qopy version to 0.3.3 in Cargo files and configuration --- src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 7004a95..64b9f84 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4075,7 +4075,7 @@ dependencies = [ [[package]] name = "qopy" -version = "0.3.2" +version = "0.3.3" dependencies = [ "active-win-pos-rs", "applications", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index d6df90d..809f47b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "qopy" -version = "0.3.2" +version = "0.3.3" description = "Qopy" authors = ["pandadev"] edition = "2021" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index daf875d..2e12a87 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,6 +1,6 @@ { "productName": "Qopy", - "version": "0.3.2", + "version": "0.3.3", "identifier": "net.pandadev.qopy", "build": { "frontendDist": "../dist", From d1f2b1ddd75d408b8dbce6d12843ac1771087cab Mon Sep 17 00:00:00 2001 From: PandaDEV Date: Sun, 29 Dec 2024 10:53:26 +1000 Subject: [PATCH 025/110] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 452991a..b06496e 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ The fixed and simple clipboard manager for both Windows and Linux. Linux (rpm) • - + Linux (AppImage)
From b9d758f3172e11cd9afc8a3d3734c56626888caf Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Mon, 30 Dec 2024 12:00:54 +1000 Subject: [PATCH 026/110] chore: update serde to 1.0.217 and reqwest to 0.12.11 in Cargo.toml --- src-tauri/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 809f47b..08142a1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -26,14 +26,14 @@ tauri-plugin-prevent-default = "1.0.1" tauri-plugin-global-shortcut = "2.2.0" tauri-plugin-aptabase = { git = "https://github.com/aptabase/tauri-plugin-aptabase", branch = "v2" } sqlx = { version = "0.8.2", features = ["runtime-tokio-native-tls", "sqlite", "chrono"] } -serde = { version = "1.0.216", features = ["derive"] } +serde = { version = "1.0.217", features = ["derive"] } tokio = { version = "1.42.0", features = ["full"] } serde_json = "1.0.134" rdev = "0.5.3" rand = "0.8.5" base64 = "0.22.1" image = "0.25.5" -reqwest = { version = "0.12.9", features = ["json", "blocking"] } +reqwest = { version = "0.12.11", features = ["json", "blocking"] } url = "2.5.4" regex = "1.11.1" sha2 = "0.10.8" From a7e221cb295047a49fa3b0f0734515223ef66141 Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Mon, 30 Dec 2024 12:00:59 +1000 Subject: [PATCH 027/110] chore: update dependencies in Cargo.lock for hyper-util, reqwest, serde, tower, and related packages --- src-tauri/Cargo.lock | 52 ++++++++++++++------------------------------ 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 64b9f84..31fba10 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2318,9 +2318,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.7" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -2331,7 +2331,6 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", - "tower", "tower-service", "tracing", ] @@ -3844,26 +3843,6 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", -] - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -4442,9 +4421,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.9" +version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +checksum = "7fe060fe50f524be480214aba758c71f99f90ee8c83c5a36b5e9e1d568eb4eb3" dependencies = [ "base64 0.22.1", "bytes", @@ -4481,6 +4460,7 @@ dependencies = [ "tokio-native-tls", "tokio-rustls", "tokio-util", + "tower", "tower-service", "url", "wasm-bindgen", @@ -4771,9 +4751,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.216" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] @@ -4791,9 +4771,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.216" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -6248,14 +6228,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.4.13" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", - "pin-project", "pin-project-lite", + "sync_wrapper", "tokio", "tower-layer", "tower-service", @@ -6263,15 +6243,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" From 0a08ce95d21b4da06d66205fa4723c95c3fc2e66 Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Mon, 30 Dec 2024 12:04:23 +1000 Subject: [PATCH 028/110] refactor: clean up main.rs by removing unused imports and simplifying main window initialization --- src-tauri/src/main.rs | 61 ++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 35 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index c6aed37..7f9fb79 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -7,14 +7,12 @@ mod api; mod db; mod utils; +use sqlx::sqlite::SqlitePoolOptions; use std::fs; use tauri::Manager; -use tauri::WebviewUrl; -use tauri::WebviewWindow; -use sqlx::sqlite::SqlitePoolOptions; +use tauri_plugin_aptabase::{EventTracker, InitOptions}; use tauri_plugin_autostart::MacosLauncher; use tauri_plugin_prevent_default::Flags; -use tauri_plugin_aptabase::{EventTracker, InitOptions}; fn main() { let runtime = tokio::runtime::Runtime::new().expect("Failed to create Tokio runtime"); @@ -27,19 +25,27 @@ fn main() { .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()); + .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()) + let _ = client.track_event( + "panic", + Some(serde_json::json!({ + "info": format!("{} ({})", msg, location), + })), + ); + })) + .build(), + ) .plugin(tauri_plugin_autostart::init( MacosLauncher::LaunchAgent, Some(vec![]), @@ -52,7 +58,7 @@ fn main() { .setup(|app| { 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"); @@ -76,22 +82,7 @@ fn main() { app_handle_clone.manage(pool); }); - let main_window = if let Some(window) = app.get_webview_window("main") { - window - } else { - WebviewWindow::builder(app.handle(), "main", WebviewUrl::App("index.html".into())) - .title("Qopy") - .resizable(false) - .fullscreen(false) - .inner_size(750.0, 474.0) - .focused(true) - .skip_taskbar(true) - .visible(false) - .decorations(false) - .transparent(true) - .always_on_top(false) - .build()? - }; + let main_window = app.get_webview_window("main"); let _ = db::database::setup(app); api::hotkeys::setup(app_handle.clone()); @@ -99,8 +90,8 @@ fn main() { api::clipboard::setup(app.handle()); let _ = api::clipboard::start_monitor(app_handle.clone()); - utils::commands::center_window_on_current_monitor(&main_window); - main_window.hide()?; + 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); From 14e8edd23840e25f944e9f8d8a988b5c7ef1994b Mon Sep 17 00:00:00 2001 From: PandaDEV Date: Wed, 1 Jan 2025 16:13:50 +1000 Subject: [PATCH 029/110] docs: add linux to os path --- GET_STARTED.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GET_STARTED.md b/GET_STARTED.md index dc761bf..548a5e9 100644 --- a/GET_STARTED.md +++ b/GET_STARTED.md @@ -8,7 +8,7 @@ All the data of Qopy is stored inside of a SQLite database. |------------------|-----------------------------------------------------------------| | Windows | `C:\Users\USERNAME\AppData\Roaming\net.pandadev.qopy` | | macOS | `/Users/USERNAME/Library/Application Support/net.pandadev.qopy` | -| Linux | `` | +| Linux | `/home/USERNAME/.local/share/net.pandadev.qopy` | ## Disable Windows+V for default clipboard manager From 0f29e0af07513f59c28c1f934f1f214c6c7e0865 Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Wed, 1 Jan 2025 16:17:13 +1000 Subject: [PATCH 030/110] chore: migrate from pnpm to bun for dependency management in workflows and update README instructions --- .github/workflows/build.yml | 24 ++++++++++---------- .github/workflows/release.yml | 42 +++++++++++++++++------------------ README.md | 8 +++---- src-tauri/tauri.conf.json | 8 +++---- 4 files changed, 40 insertions(+), 42 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4c23943..afe4e08 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -56,11 +56,11 @@ jobs: save-if: "true" - uses: actions/cache@v4 with: - path: ~/.pnpm-store - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ~/.bun + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} restore-keys: | - ${{ runner.os }}-pnpm- - - run: npm install -g pnpm && pnpm install + ${{ runner.os }}-bun- + - run: curl -fsSL https://bun.sh/install | bash && bun install - name: Import Apple Developer Certificate env: APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} @@ -143,11 +143,11 @@ jobs: save-if: "true" - uses: actions/cache@v4 with: - path: ~/.pnpm-store - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ~/.bun + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} restore-keys: | - ${{ runner.os }}-pnpm- - - run: npm install -g pnpm && pnpm install + ${{ runner.os }}-bun- + - run: curl -fsSL https://bun.sh/install | bash && bun install - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -199,16 +199,16 @@ jobs: save-if: "true" - uses: actions/cache@v4 with: - path: ~/.pnpm-store - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ~/.bun + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} restore-keys: | - ${{ runner.os }}-pnpm- + ${{ runner.os }}-bun- - 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 + - run: curl -fsSL https://bun.sh/install | bash && bun install - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f79b85d..99ce4e6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -57,11 +57,11 @@ jobs: save-if: "true" - uses: actions/cache@v4 with: - path: ~/.pnpm-store - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ~/.bun + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} restore-keys: | - ${{ runner.os }}-pnpm- - - run: npm install -g pnpm && pnpm install + ${{ runner.os }}-bun- + - run: curl -fsSL https://bun.sh/install | bash && bun install - name: Import Apple Developer Certificate env: APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} @@ -83,7 +83,7 @@ jobs: 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 @@ -125,11 +125,11 @@ jobs: save-if: "true" - uses: actions/cache@v4 with: - path: ~/.pnpm-store - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ~/.bun + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} restore-keys: | - ${{ runner.os }}-pnpm- - - run: npm install -g pnpm && pnpm install + ${{ runner.os }}-bun- + - run: curl -fsSL https://bun.sh/install | bash && bun install - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -189,16 +189,16 @@ jobs: save-if: "true" - uses: actions/cache@v4 with: - path: ~/.pnpm-store - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ~/.bun + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} restore-keys: | - ${{ runner.os }}-pnpm- + ${{ runner.os }}-bun- - 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 + - run: curl -fsSL https://bun.sh/install | bash && bun install - name: Generate Changelog id: changelog run: | @@ -243,10 +243,10 @@ jobs: id: release_body run: | VERSION="${{ needs.prepare.outputs.version }}" - + # Get the most recent release tag (v* tags only) LAST_TAG=$(git describe --match "v*" --abbrev=0 --tags `git rev-list --tags --skip=1 --max-count=1` 2>/dev/null || echo "") - + if [ -n "$LAST_TAG" ]; then echo "Debug: Found last release tag: $LAST_TAG" CHANGES=$(git log ${LAST_TAG}..HEAD --pretty=format:"- %s") @@ -254,10 +254,10 @@ jobs: echo "Debug: No previous release tag found, using first commit" CHANGES=$(git log --pretty=format:"- %s") fi - + echo "Debug: Changelog content:" echo "$CHANGES" - + # 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 }') @@ -279,11 +279,11 @@ jobs: RELEASE_BODY=$(cat <<-EOF ## ♻️ Changelog - + $CHANGES - + ## ⬇️ 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} @@ -312,4 +312,4 @@ jobs: artifacts/**/*.deb artifacts/**/*.AppImage artifacts/**/*.rpm - body: ${{ env.RELEASE_BODY }} \ No newline at end of file + body: ${{ env.RELEASE_BODY }} diff --git a/README.md b/README.md index b06496e..3d76477 100644 --- a/README.md +++ b/README.md @@ -95,13 +95,13 @@ 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 pnpm installed. Then, follow these steps: +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 -pnpm i -pnpm dev +bun i +bun dev ``` > \[!TIP] @@ -113,7 +113,7 @@ pnpm dev To build for production simply execute: ```zsh -pnpm build +bun build ``` > \[!NOTE] diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 2e12a87..2cfde48 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -5,8 +5,8 @@ "build": { "frontendDist": "../dist", "devUrl": "http://localhost:3000", - "beforeDevCommand": "pnpm nuxt dev", - "beforeBuildCommand": "pnpm nuxt generate" + "beforeDevCommand": "bun nuxt dev", + "beforeBuildCommand": "bun nuxt generate" }, "app": { "windows": [ @@ -51,9 +51,7 @@ "plugins": { "updater": { "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDExNDIzNjA1QjE0NjU1OTkKUldTWlZVYXhCVFpDRWNvNmt0UE5lQmZkblEyZGZiZ2tHelJvT2YvNVpLU1RIM1RKZFQrb2tzWWwK", - "endpoints": [ - "https://qopy.pandadev.net/" - ] + "endpoints": ["https://qopy.pandadev.net/"] } }, "$schema": "../node_modules/@tauri-apps/cli/schema.json" From b3daaaa633ee00c01fcf6ba4737916133356f5c6 Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Wed, 1 Jan 2025 17:43:35 +1000 Subject: [PATCH 031/110] fix: back button not wroking on settings --- assets/css/settings.scss | 1 + pages/settings.vue | 58 ++++++++++++++++++++++++---------------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/assets/css/settings.scss b/assets/css/settings.scss index c3ad9d4..c7d829a 100644 --- a/assets/css/settings.scss +++ b/assets/css/settings.scss @@ -43,6 +43,7 @@ $mutedtext: #78756F; justify-content: center; height: 100vh; gap: 6px; + z-index: -1; .title { font-size: 20px; diff --git a/pages/settings.vue b/pages/settings.vue index 6fd6417..dbf51c4 100644 --- a/pages/settings.vue +++ b/pages/settings.vue @@ -1,9 +1,9 @@ YouTube Thumbnail -
- Image +
+ Image
{{ selectedItem?.content || "" }} @@ -135,9 +146,7 @@

{{ row.label }}

- + {{ row.value }}
@@ -158,7 +167,15 @@ import { listen } from "@tauri-apps/api/event"; import { useNuxtApp } from "#app"; import { invoke } from "@tauri-apps/api/core"; import { HistoryItem, ContentType } from "~/types/types"; -import type { InfoText, InfoImage, InfoFile, InfoLink, InfoColor, InfoCode } from "~/types/types"; +import type { + InfoText, + InfoImage, + InfoFile, + InfoLink, + InfoColor, + InfoCode, +} from "~/types/types"; +import { Key } from "wrdu-keyboard/key"; interface GroupedHistory { label: string; @@ -188,8 +205,8 @@ const imageSizes = shallowRef>({}); const lastUpdateTime = ref(Date.now()); const imageLoadError = ref(false); const imageLoading = ref(false); -const pageTitle = ref(''); -const pageOgImage = ref(''); +const pageTitle = ref(""); +const pageOgImage = ref(""); const keyboard = useKeyboard(); @@ -583,41 +600,35 @@ const setupEventListeners = async (): Promise => { searchInput.value?.blur(); }); - keyboard.down("ArrowDown", (event) => { - event.preventDefault(); + keyboard.prevent.down([Key.DownArrow], (event) => { selectNext(); }); - keyboard.down("ArrowUp", (event) => { - event.preventDefault(); + keyboard.prevent.down([Key.UpArrow], (event) => { selectPrevious(); }); - keyboard.down("Enter", (event) => { - event.preventDefault(); + keyboard.prevent.down([Key.Enter], (event) => { pasteSelectedItem(); }); - keyboard.down("Escape", (event) => { - event.preventDefault(); + keyboard.prevent.down([Key.Escape], (event) => { hideApp(); }); - keyboard.down("all", (event) => { - const isMacActionCombo = - os.value === "macos" && - (event.code === "MetaLeft" || event.code === "MetaRight") && - event.key === "k"; + switch (os.value) { + case "macos": + keyboard.prevent.down([Key.LeftMeta, Key.K], (event) => {}); - const isOtherOsActionCombo = - os.value !== "macos" && - (event.code === "ControlLeft" || event.code === "ControlRight") && - event.key === "k"; + keyboard.prevent.down([Key.RightMeta, Key.K], (event) => {}); + break; - if (isMacActionCombo || isOtherOsActionCombo) { - event.preventDefault(); - } - }); + case "linux" || "windows": + keyboard.prevent.down([Key.LeftControl, Key.K], (event) => {}); + + keyboard.prevent.down([Key.RightControl, Key.K], (event) => {}); + break; + } }; const hideApp = async (): Promise => { @@ -646,7 +657,7 @@ watch(searchQuery, () => { onMounted(async () => { try { - os.value = await platform(); + os.value = platform(); await loadHistoryChunk(); resultsContainer.value @@ -686,27 +697,33 @@ const formatFileSize = (bytes: number): string => { const fetchPageMeta = async (url: string) => { try { - const [title, ogImage] = await invoke('fetch_page_meta', { url }) as [string, string | null]; + const [title, ogImage] = (await invoke("fetch_page_meta", { url })) as [ + string, + string | null + ]; pageTitle.value = title; if (ogImage) { pageOgImage.value = ogImage; } } catch (error) { - console.error('Error fetching page meta:', error); - pageTitle.value = 'Error loading title'; + console.error("Error fetching page meta:", error); + pageTitle.value = "Error loading title"; } }; -watch(() => selectedItem.value, (newItem) => { - if (newItem?.content_type === ContentType.Link) { - pageTitle.value = 'Loading...'; - pageOgImage.value = ''; - fetchPageMeta(newItem.content); - } else { - pageTitle.value = ''; - pageOgImage.value = ''; +watch( + () => selectedItem.value, + (newItem) => { + if (newItem?.content_type === ContentType.Link) { + pageTitle.value = "Loading..."; + pageOgImage.value = ""; + fetchPageMeta(newItem.content); + } else { + pageTitle.value = ""; + pageOgImage.value = ""; + } } -}); +); const getInfo = computed(() => { if (!selectedItem.value) return null; @@ -716,7 +733,10 @@ const getInfo = computed(() => { copied: selectedItem.value.timestamp, }; - const infoMap: Record InfoText | InfoImage | InfoFile | InfoLink | InfoColor | InfoCode> = { + const infoMap: Record< + ContentType, + () => InfoText | InfoImage | InfoFile | InfoLink | InfoColor | InfoCode + > = { [ContentType.Text]: () => ({ ...baseInfo, content_type: ContentType.Text, @@ -747,20 +767,21 @@ const getInfo = computed(() => { const r = parseInt(hex.slice(1, 3), 16); const g = parseInt(hex.slice(3, 5), 16); const b = parseInt(hex.slice(5, 7), 16); - + const rNorm = r / 255; const gNorm = g / 255; const bNorm = b / 255; - + const max = Math.max(rNorm, gNorm, bNorm); const min = Math.min(rNorm, gNorm, bNorm); - let h = 0, s = 0; + let h = 0, + s = 0; const l = (max + min) / 2; if (max !== min) { const d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - + switch (max) { case rNorm: h = (gNorm - bNorm) / d + (gNorm < bNorm ? 6 : 0); @@ -780,14 +801,16 @@ const getInfo = computed(() => { content_type: ContentType.Color, hex: hex, rgb: `rgb(${r}, ${g}, ${b})`, - hsl: `hsl(${Math.round(h * 360)}, ${Math.round(s * 100)}%, ${Math.round(l * 100)}%)`, + hsl: `hsl(${Math.round(h * 360)}, ${Math.round(s * 100)}%, ${Math.round( + l * 100 + )}%)`, }; }, [ContentType.Code]: () => ({ ...baseInfo, content_type: ContentType.Code, language: selectedItem.value!.language ?? "Unknown", - lines: selectedItem.value!.content.split('\n').length, + lines: selectedItem.value!.content.split("\n").length, }), }; @@ -799,24 +822,37 @@ const infoRows = computed(() => { const commonRows = [ { label: "Source", value: getInfo.value.source, isUrl: false }, - { label: "Content Type", value: getInfo.value.content_type.charAt(0).toUpperCase() + getInfo.value.content_type.slice(1), isUrl: false }, + { + label: "Content Type", + value: + getInfo.value.content_type.charAt(0).toUpperCase() + + getInfo.value.content_type.slice(1), + isUrl: false, + }, ]; - const typeSpecificRows: Record> = { + const typeSpecificRows: Record< + ContentType, + Array<{ label: string; value: string | number; isUrl?: boolean }> + > = { [ContentType.Text]: [ { label: "Characters", value: (getInfo.value as InfoText).characters }, { label: "Words", value: (getInfo.value as InfoText).words }, ], [ContentType.Image]: [ { label: "Dimensions", value: (getInfo.value as InfoImage).dimensions }, - { label: "Image size", value: formatFileSize((getInfo.value as InfoImage).size) }, + { + label: "Image size", + value: formatFileSize((getInfo.value as InfoImage).size), + }, ], [ContentType.File]: [ { label: "Path", value: (getInfo.value as InfoFile).path }, ], [ContentType.Link]: [ - ...((getInfo.value as InfoLink).title && (getInfo.value as InfoLink).title !== 'Loading...' - ? [{ label: "Title", value: (getInfo.value as InfoLink).title || '' }] + ...((getInfo.value as InfoLink).title && + (getInfo.value as InfoLink).title !== "Loading..." + ? [{ label: "Title", value: (getInfo.value as InfoLink).title || "" }] : []), { label: "URL", value: (getInfo.value as InfoLink).url, isUrl: true }, { label: "Characters", value: (getInfo.value as InfoLink).characters }, @@ -832,8 +868,9 @@ const infoRows = computed(() => { ], }; - const specificRows = typeSpecificRows[getInfo.value.content_type] - .filter(row => row.value !== ""); + const specificRows = typeSpecificRows[getInfo.value.content_type].filter( + (row) => row.value !== "" + ); return [ ...commonRows, diff --git a/patches/wrdu-keyboard@3.0.0.patch b/patches/wrdu-keyboard@3.0.0.patch new file mode 100644 index 0000000..e973647 --- /dev/null +++ b/patches/wrdu-keyboard@3.0.0.patch @@ -0,0 +1,123 @@ +diff --git a/node_modules/wrdu-keyboard/.DS_Store b/.DS_Store +new file mode 100644 +index 0000000000000000000000000000000000000000..fabbd951c2d14c46fd10fa167b8836d116bc0db6 +Binary files /dev/null and b/.DS_Store differ +diff --git a/dist/runtime/keyboard.d.ts b/dist/runtime/keyboard.d.ts +index aeae40f3d2bc3efd459cce04c29c21c43884154d..6131bab4895ebb3048a5225f366430d23c5f1f13 100644 +--- a/dist/runtime/keyboard.d.ts ++++ b/dist/runtime/keyboard.d.ts +@@ -1,15 +1,16 @@ +-import { Key } from './types/keys.js'; +-import { type Plugin } from '#app'; ++import { Key } from "./types/keys.js"; ++import { type Plugin } from "#app"; + type Handler = (event: KeyboardEvent) => void; + type Config = { + once?: boolean; + prevent?: boolean; + }; +-type PublicConfig = Omit; ++type PublicConfig = Omit; + type New = (keys: Key[], handler: Handler, config?: PublicConfig) => void; + export interface Keyboard { + init: () => void; + stop: () => void; ++ unregisterAll: () => void; + down: New; + up: New; + prevent: { +diff --git a/dist/runtime/keyboard.js b/dist/runtime/keyboard.js +index e16f600258cee90d185ffc52777bed95c14bd93e..e4ce2678db649ec82e5a67fcdb74f5cdb37820aa 100644 +--- a/dist/runtime/keyboard.js ++++ b/dist/runtime/keyboard.js +@@ -1,13 +1,14 @@ + import { Key } from "./types/keys.js"; + import { defineNuxtPlugin } from "#app"; +-const getKeyString = (keys) => keys[0] == Key.All ? keys.sort().join("+") : "All"; ++const getKeyString = (keys) => keys.includes(Key.All) ? "All" : keys.sort().join("+"); + const handlers = { + down: {}, + up: {} + }; + const pressedKeys = /* @__PURE__ */ new Set(); + const onKeydown = (event) => { +- pressedKeys.add(event.code); ++ const key = event.code; ++ pressedKeys.add(key); + const pressedArray = Array.from(pressedKeys); + const keyString = getKeyString(pressedArray); + if (handlers.down[keyString]) { +@@ -17,13 +18,16 @@ const onKeydown = (event) => { + } + eventHandler.handler(event); + if (eventHandler.once) { +- handlers.down[keyString] = handlers.down[keyString].filter((h) => h !== eventHandler); ++ handlers.down[keyString] = handlers.down[keyString].filter( ++ (h) => h !== eventHandler ++ ); + } + }); + } + }; + const onKeyup = (event) => { +- pressedKeys.delete(event.code); ++ const key = event.code; ++ pressedKeys.delete(key); + const releasedArray = Array.from(pressedKeys); + const keyString = getKeyString(releasedArray); + if (handlers.up[keyString]) { +@@ -33,13 +37,16 @@ const onKeyup = (event) => { + } + eventHandler.handler(event); + if (eventHandler.once) { +- handlers.up[keyString] = handlers.up[keyString].filter((h) => h !== eventHandler); ++ handlers.up[keyString] = handlers.up[keyString].filter( ++ (h) => h !== eventHandler ++ ); + } + }); + } + }; + const init = () => { + stop(); ++ pressedKeys.clear(); + window.addEventListener("keydown", onKeydown); + window.addEventListener("keyup", onKeyup); + }; +@@ -47,6 +54,20 @@ const stop = () => { + window.removeEventListener("keydown", onKeydown); + window.removeEventListener("keyup", onKeyup); + }; ++const unregisterAll = () => { ++ Object.keys(handlers.down).forEach((key) => { ++ handlers.down[key].forEach((handler) => { ++ console.log(`Unregistering ${key} ${handler.handler.toString()}`); ++ }); ++ }); ++ Object.keys(handlers.up).forEach((key) => { ++ handlers.up[key].forEach((handler) => { ++ console.log(`Unregistering ${key} ${handler.handler.toString()}`); ++ }); ++ }); ++ handlers.down = {}; ++ handlers.up = {}; ++}; + const down = (keys, handler, config = {}) => { + if (keys.includes(Key.All)) { + keys = [Key.All]; +@@ -59,6 +80,7 @@ const down = (keys, handler, config = {}) => { + handlers.down[key] = []; + } + const { once = false, prevent = false } = config; ++ console.log(key, handler.toString()); + handlers.down[key].push({ handler, prevent, once }); + }; + const up = (keys, handler, config = {}) => { +@@ -84,6 +106,7 @@ const keyboard = defineNuxtPlugin((nuxtApp) => { + keyboard: { + init, + stop, ++ unregisterAll, + down: (keys, handler, config = {}) => down(keys, handler, config), + up: (keys, handler, config = {}) => up(keys, handler, config), + prevent: { From 6656af8ab1409b91d0f561d100e22dec5b108016 Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Thu, 2 Jan 2025 14:54:47 +1000 Subject: [PATCH 039/110] chore: Update wrdu-keyboard to version 3.0.0 --- package.json | 5 ++++- src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e605d31..de5e05e 100644 --- a/package.json +++ b/package.json @@ -20,9 +20,12 @@ "sass-embedded": "1.83.0", "uuid": "11.0.3", "vue": "3.5.13", - "wrdu-keyboard": "1.1.1" + "wrdu-keyboard": "3.0.0" }, "overrides": { "chokidar": "^3.6.0" + }, + "patchedDependencies": { + "wrdu-keyboard@3.0.0": "patches/wrdu-keyboard@3.0.0.patch" } } diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 31fba10..a5d7869 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4054,7 +4054,7 @@ dependencies = [ [[package]] name = "qopy" -version = "0.3.3" +version = "0.3.4" dependencies = [ "active-win-pos-rs", "applications", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 08142a1..45e9dd7 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "qopy" -version = "0.3.3" +version = "0.3.4" description = "Qopy" authors = ["pandadev"] edition = "2021" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 2cfde48..10ae2a2 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,6 +1,6 @@ { "productName": "Qopy", - "version": "0.3.3", + "version": "0.3.4", "identifier": "net.pandadev.qopy", "build": { "frontendDist": "../dist", From 0c28a5b0dbc9c7e1668a515e4109eb21c691d386 Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Thu, 2 Jan 2025 17:05:02 +1000 Subject: [PATCH 040/110] refactor: improve keybind saving logic and error handling --- GET_STARTED.md | 4 +- pages/settings.vue | 71 ++++------ patches/wrdu-keyboard@3.0.0.patch | 98 +++++++------- src-tauri/src/api/hotkeys.rs | 114 ++++++++-------- src-tauri/src/db/settings.rs | 9 +- src-tauri/src/utils/keys.rs | 118 ++++++++++++++++ src-tauri/src/utils/mod.rs | 1 + types/keys.ts | 217 ++++++++++++++++++++++++++++++ 8 files changed, 478 insertions(+), 154 deletions(-) create mode 100644 src-tauri/src/utils/keys.rs create mode 100644 types/keys.ts diff --git a/GET_STARTED.md b/GET_STARTED.md index 548a5e9..a793041 100644 --- a/GET_STARTED.md +++ b/GET_STARTED.md @@ -1,6 +1,6 @@ # 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). +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. @@ -12,7 +12,7 @@ All the data of Qopy is stored inside of a SQLite database. ## Disable Windows+V for default clipboard manager -https://github.com/user-attachments/assets/723f9e07-3190-46ec-9bb7-15dfc112f620 + To disable the default clipboard manager popup from windows open Command prompt and run this command diff --git a/pages/settings.vue b/pages/settings.vue index cf4771e..7a20eb1 100644 --- a/pages/settings.vue +++ b/pages/settings.vue @@ -33,7 +33,6 @@
@@ -44,7 +43,7 @@ class="key" :class="{ modifier: isModifier(key) }" v-for="(key, index) in keybind"> - {{ keyToDisplay(key) }} + {{ keyToLabel(key) }}
@@ -58,10 +57,11 @@ import { onMounted, onUnmounted, reactive, ref } from "vue"; import { platform } from "@tauri-apps/plugin-os"; import { useRouter } from "vue-router"; import { Key } from "wrdu-keyboard/key"; +import { KeyValues, KeyLabels } from "../types/keys"; -const activeModifiers = reactive>(new Set()); +const activeModifiers = reactive>(new Set()); const isKeybindInputFocused = ref(false); -const keybind = ref([]); +const keybind = ref([]); const keybindInput = ref(null); const lastBlurTime = ref(0); const os = ref(""); @@ -69,52 +69,27 @@ const router = useRouter(); const keyboard = useKeyboard(); const showEmptyKeybindError = ref(false); -const keyToDisplayMap: Record = { - " ": "Space", - Alt: "Alt", - AltLeft: "Alt L", - AltRight: "Alt R", - ArrowDown: "↓", - ArrowLeft: "←", - ArrowRight: "→", - ArrowUp: "↑", - Control: "Ctrl", - ControlLeft: "Ctrl L", - ControlRight: "Ctrl R", - Enter: "↵", - Meta: "Meta", - MetaLeft: "Meta L", - MetaRight: "Meta R", - Shift: "⇧", - ShiftLeft: "⇧ L", - ShiftRight: "⇧ R", -}; - const modifierKeySet = new Set([ - "Alt", - "AltLeft", - "AltRight", - "Control", - "ControlLeft", - "ControlRight", - "Meta", - "MetaLeft", - "MetaRight", - "Shift", - "ShiftLeft", - "ShiftRight", + KeyValues.AltLeft, + KeyValues.AltRight, + KeyValues.ControlLeft, + KeyValues.ControlRight, + KeyValues.MetaLeft, + KeyValues.MetaRight, + KeyValues.ShiftLeft, + KeyValues.ShiftRight, ]); -const isModifier = (key: string): boolean => { +const isModifier = (key: KeyValues): boolean => { return modifierKeySet.has(key); }; -const keyToDisplay = (key: string): string => { - return keyToDisplayMap[key] || key; +const keyToLabel = (key: KeyValues): string => { + return KeyLabels[key] || key; }; const updateKeybind = () => { - const modifiers = Array.from(activeModifiers).sort(); + const modifiers = Array.from(activeModifiers); const nonModifiers = keybind.value.filter((key) => !isModifier(key)); keybind.value = [...modifiers, ...nonModifiers]; }; @@ -133,9 +108,9 @@ const onFocus = () => { }; const onKeyDown = (event: KeyboardEvent) => { - const key = event.code; + const key = event.code as KeyValues; - if (key === "Escape") { + if (key === KeyValues.Escape) { if (keybindInput.value) { keybindInput.value.blur(); } @@ -155,8 +130,7 @@ const onKeyDown = (event: KeyboardEvent) => { const saveKeybind = async () => { if (keybind.value.length > 0) { - console.log("Saving keybind", keybind.value); - await invoke("save_keybind", { keybind: keybind }); + await invoke("save_keybind", { keybind: keybind.value }); } else { showEmptyKeybindError.value = true; } @@ -165,8 +139,13 @@ const saveKeybind = async () => { os.value = platform(); onMounted(() => { + keyboard.down([Key.All], (event) => { + if (isKeybindInputFocused.value) { + onKeyDown(event); + } + }); + keyboard.down([Key.Escape], (event) => { - console.log("Escape key pressed"); if (isKeybindInputFocused.value) { keybindInput.value?.blur(); } else { diff --git a/patches/wrdu-keyboard@3.0.0.patch b/patches/wrdu-keyboard@3.0.0.patch index e973647..bc77583 100644 --- a/patches/wrdu-keyboard@3.0.0.patch +++ b/patches/wrdu-keyboard@3.0.0.patch @@ -1,6 +1,6 @@ diff --git a/node_modules/wrdu-keyboard/.DS_Store b/.DS_Store new file mode 100644 -index 0000000000000000000000000000000000000000..fabbd951c2d14c46fd10fa167b8836d116bc0db6 +index 0000000000000000000000000000000000000000..4b7e9446f3580fab3e4feaba097bcdaf98c5833c Binary files /dev/null and b/.DS_Store differ diff --git a/dist/runtime/keyboard.d.ts b/dist/runtime/keyboard.d.ts index aeae40f3d2bc3efd459cce04c29c21c43884154d..6131bab4895ebb3048a5225f366430d23c5f1f13 100644 @@ -27,10 +27,10 @@ index aeae40f3d2bc3efd459cce04c29c21c43884154d..6131bab4895ebb3048a5225f366430d2 up: New; prevent: { diff --git a/dist/runtime/keyboard.js b/dist/runtime/keyboard.js -index e16f600258cee90d185ffc52777bed95c14bd93e..e4ce2678db649ec82e5a67fcdb74f5cdb37820aa 100644 +index e16f600258cee90d185ffc52777bed95c14bd93e..5ddec447a5dc66ffe063eb9f9dd765c9045bdaf7 100644 --- a/dist/runtime/keyboard.js +++ b/dist/runtime/keyboard.js -@@ -1,13 +1,14 @@ +@@ -1,45 +1,54 @@ import { Key } from "./types/keys.js"; import { defineNuxtPlugin } from "#app"; -const getKeyString = (keys) => keys[0] == Key.All ? keys.sort().join("+") : "All"; @@ -45,18 +45,31 @@ index e16f600258cee90d185ffc52777bed95c14bd93e..e4ce2678db649ec82e5a67fcdb74f5cd + const key = event.code; + pressedKeys.add(key); const pressedArray = Array.from(pressedKeys); - const keyString = getKeyString(pressedArray); - if (handlers.down[keyString]) { -@@ -17,13 +18,16 @@ const onKeydown = (event) => { - } - eventHandler.handler(event); - if (eventHandler.once) { +- const keyString = getKeyString(pressedArray); +- if (handlers.down[keyString]) { +- handlers.down[keyString].forEach((eventHandler) => { +- if (eventHandler.prevent) { +- event.preventDefault(); +- } +- eventHandler.handler(event); +- if (eventHandler.once) { - handlers.down[keyString] = handlers.down[keyString].filter((h) => h !== eventHandler); -+ handlers.down[keyString] = handlers.down[keyString].filter( -+ (h) => h !== eventHandler -+ ); - } - }); +- } +- }); ++ for (const keyString of [getKeyString(pressedArray), "All"]) { ++ if (handlers.down[keyString]) { ++ handlers.down[keyString].forEach((eventHandler) => { ++ if (eventHandler.prevent) { ++ event.preventDefault(); ++ } ++ eventHandler.handler(event); ++ if (eventHandler.once) { ++ handlers.down[keyString] = handlers.down[keyString].filter( ++ (h) => h !== eventHandler ++ ); ++ } ++ }); ++ } } }; const onKeyup = (event) => { @@ -64,18 +77,31 @@ index e16f600258cee90d185ffc52777bed95c14bd93e..e4ce2678db649ec82e5a67fcdb74f5cd + const key = event.code; + pressedKeys.delete(key); const releasedArray = Array.from(pressedKeys); - const keyString = getKeyString(releasedArray); - if (handlers.up[keyString]) { -@@ -33,13 +37,16 @@ const onKeyup = (event) => { - } - eventHandler.handler(event); - if (eventHandler.once) { +- const keyString = getKeyString(releasedArray); +- if (handlers.up[keyString]) { +- handlers.up[keyString].forEach((eventHandler) => { +- if (eventHandler.prevent) { +- event.preventDefault(); +- } +- eventHandler.handler(event); +- if (eventHandler.once) { - handlers.up[keyString] = handlers.up[keyString].filter((h) => h !== eventHandler); -+ handlers.up[keyString] = handlers.up[keyString].filter( -+ (h) => h !== eventHandler -+ ); - } - }); +- } +- }); ++ for (const keyString of [getKeyString(releasedArray), "All"]) { ++ if (handlers.up[keyString]) { ++ handlers.up[keyString].forEach((eventHandler) => { ++ if (eventHandler.prevent) { ++ event.preventDefault(); ++ } ++ eventHandler.handler(event); ++ if (eventHandler.once) { ++ handlers.up[keyString] = handlers.up[keyString].filter( ++ (h) => h !== eventHandler ++ ); ++ } ++ }); ++ } } }; const init = () => { @@ -84,36 +110,18 @@ index e16f600258cee90d185ffc52777bed95c14bd93e..e4ce2678db649ec82e5a67fcdb74f5cd window.addEventListener("keydown", onKeydown); window.addEventListener("keyup", onKeyup); }; -@@ -47,6 +54,20 @@ const stop = () => { +@@ -47,6 +56,10 @@ const stop = () => { window.removeEventListener("keydown", onKeydown); window.removeEventListener("keyup", onKeyup); }; +const unregisterAll = () => { -+ Object.keys(handlers.down).forEach((key) => { -+ handlers.down[key].forEach((handler) => { -+ console.log(`Unregistering ${key} ${handler.handler.toString()}`); -+ }); -+ }); -+ Object.keys(handlers.up).forEach((key) => { -+ handlers.up[key].forEach((handler) => { -+ console.log(`Unregistering ${key} ${handler.handler.toString()}`); -+ }); -+ }); + handlers.down = {}; + handlers.up = {}; +}; const down = (keys, handler, config = {}) => { if (keys.includes(Key.All)) { keys = [Key.All]; -@@ -59,6 +80,7 @@ const down = (keys, handler, config = {}) => { - handlers.down[key] = []; - } - const { once = false, prevent = false } = config; -+ console.log(key, handler.toString()); - handlers.down[key].push({ handler, prevent, once }); - }; - const up = (keys, handler, config = {}) => { -@@ -84,6 +106,7 @@ const keyboard = defineNuxtPlugin((nuxtApp) => { +@@ -84,6 +97,7 @@ const keyboard = defineNuxtPlugin((nuxtApp) => { keyboard: { init, stop, diff --git a/src-tauri/src/api/hotkeys.rs b/src-tauri/src/api/hotkeys.rs index 0470e24..52a276b 100644 --- a/src-tauri/src/api/hotkeys.rs +++ b/src-tauri/src/api/hotkeys.rs @@ -1,48 +1,61 @@ -use tauri_plugin_aptabase::EventTracker; 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 std::cell::RefCell; +use lazy_static::lazy_static; use std::str::FromStr; +use std::sync::Mutex; use tauri::{AppHandle, Listener, Manager}; +use tauri_plugin_aptabase::EventTracker; -thread_local! { - static HOTKEY_MANAGER: RefCell> = RefCell::new(None); +lazy_static! { + static ref HOTKEY_MANAGER: Mutex> = Mutex::new(None); + static ref REGISTERED_HOTKEYS: Mutex> = Mutex::new(Vec::new()); } pub fn setup(app_handle: tauri::AppHandle) { let app_handle_clone = app_handle.clone(); - let manager = GlobalHotKeyManager::new().expect("Failed to initialize hotkey manager"); - HOTKEY_MANAGER.with(|m| *m.borrow_mut() = Some(manager)); + let manager = match GlobalHotKeyManager::new() { + Ok(manager) => manager, + Err(err) => { + eprintln!("Failed to initialize hotkey manager: {:?}", err); + return; + } + }; + + { + let mut manager_guard = HOTKEY_MANAGER.lock().unwrap(); + *manager_guard = Some(manager); + } let rt = app_handle.state::(); let initial_keybind = rt .block_on(crate::db::settings::get_keybind(app_handle_clone.clone())) .expect("Failed to get initial keybind"); - let initial_shortcut = initial_keybind.join("+"); - let initial_shortcut_for_update = initial_shortcut.clone(); - let initial_shortcut_for_save = initial_shortcut.clone(); + let initial_shortcut_for_update = initial_keybind.clone(); + let initial_shortcut_for_save = initial_keybind.clone(); - if let Err(e) = register_shortcut(&initial_shortcut) { + if let Err(e) = register_shortcut(&initial_keybind) { eprintln!("Error registering initial shortcut: {:?}", e); } app_handle.listen("update-shortcut", move |event| { - let payload_str = event.payload().to_string(); + let payload_str = event.payload(); if let Ok(old_hotkey) = parse_hotkey(&initial_shortcut_for_update) { - HOTKEY_MANAGER.with(|manager| { - if let Some(manager) = manager.borrow().as_ref() { - let _ = manager.unregister(old_hotkey); - } - }); + let manager_guard = HOTKEY_MANAGER.lock().unwrap(); + if let Some(manager) = manager_guard.as_ref() { + let _ = manager.unregister(old_hotkey); + } } - if let Err(e) = register_shortcut(&payload_str) { + let payload: Vec = serde_json::from_str(payload_str).unwrap_or_default(); + + if let Err(e) = register_shortcut(&payload) { eprintln!("Error re-registering shortcut: {:?}", e); } }); @@ -51,14 +64,14 @@ pub fn setup(app_handle: tauri::AppHandle) { let payload_str = event.payload().to_string(); if let Ok(old_hotkey) = parse_hotkey(&initial_shortcut_for_save) { - HOTKEY_MANAGER.with(|manager| { - if let Some(manager) = manager.borrow().as_ref() { - let _ = manager.unregister(old_hotkey); - } - }); + let manager_guard = HOTKEY_MANAGER.lock().unwrap(); + if let Some(manager) = manager_guard.as_ref() { + let _ = manager.unregister(old_hotkey); + } } - if let Err(e) = register_shortcut(&payload_str) { + let payload: Vec = serde_json::from_str(&payload_str).unwrap_or_default(); + if let Err(e) = register_shortcut(&payload) { eprintln!("Error registering saved shortcut: {:?}", e); } }); @@ -81,48 +94,36 @@ pub fn setup(app_handle: tauri::AppHandle) { }); } -fn register_shortcut(shortcut: &str) -> Result<(), Box> { +fn register_shortcut(shortcut: &[String]) -> Result<(), Box> { let hotkey = parse_hotkey(shortcut)?; - HOTKEY_MANAGER.with(|manager| { - if let Some(manager) = manager.borrow().as_ref() { - manager.register(hotkey)?; - } + + let manager_guard = HOTKEY_MANAGER.lock().unwrap(); + if let Some(manager) = manager_guard.as_ref() { + manager.register(hotkey.clone())?; + REGISTERED_HOTKEYS.lock().unwrap().push(hotkey); Ok(()) - }) + } else { + Err("Hotkey manager not initialized".into()) + } } -fn parse_hotkey(shortcut: &str) -> Result> { +fn parse_hotkey(shortcut: &[String]) -> Result> { let mut modifiers = Modifiers::empty(); let mut code = None; - let shortcut = shortcut.replace("\"", ""); - - for part in shortcut.split('+') { - let part = part.trim().to_lowercase(); + for part in shortcut { match part.as_str() { - "ctrl" | "control" | "controlleft" => modifiers |= Modifiers::CONTROL, - "alt" | "altleft" | "optionleft" => modifiers |= Modifiers::ALT, - "shift" | "shiftleft" => modifiers |= Modifiers::SHIFT, - "super" | "meta" | "cmd" | "metaleft" => modifiers |= Modifiers::META, + "ControlLeft" => modifiers |= Modifiers::CONTROL, + "AltLeft" => modifiers |= Modifiers::ALT, + "ShiftLeft" => modifiers |= Modifiers::SHIFT, + "MetaLeft" => modifiers |= Modifiers::META, key => { - let key_code = if key.starts_with("key") { - "Key".to_string() + &key[3..].to_uppercase() - } else if key.len() == 1 && key.chars().next().unwrap().is_alphabetic() { - "Key".to_string() + &key.to_uppercase() - } else { - key.to_string() - }; - - code = Some( - Code::from_str(&key_code) - .map_err(|_| format!("Invalid key code: {}", key_code))?, - ); + code = Some(Code::from(KeyCode::from_str(key)?)); } } } - let key_code = - code.ok_or_else(|| format!("No valid key code found in shortcut: {}", shortcut))?; + let key_code = code.ok_or_else(|| "No valid key code found".to_string())?; Ok(HotKey::new(Some(modifiers), key_code)) } @@ -144,7 +145,10 @@ fn handle_hotkey_event(app_handle: &AppHandle) { 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" } - }))); + let _ = app_handle.track_event( + "hotkey_triggered", + Some(serde_json::json!({ + "action": if window.is_visible().unwrap() { "hide" } else { "show" } + })), + ); } diff --git a/src-tauri/src/db/settings.rs b/src-tauri/src/db/settings.rs index bdd6f58..7fedf8c 100644 --- a/src-tauri/src/db/settings.rs +++ b/src-tauri/src/db/settings.rs @@ -30,11 +30,8 @@ pub async fn save_keybind( pool: tauri::State<'_, SqlitePool>, keybind: Vec, ) -> Result<(), String> { - let keybind_str = keybind.join("+"); - let keybind_clone = keybind_str.clone(); - app_handle - .emit("update-shortcut", &keybind_str) + .emit("update-shortcut", &keybind) .map_err(|e| e.to_string())?; let json = serde_json::to_string(&keybind).map_err(|e| e.to_string())?; @@ -46,7 +43,7 @@ pub async fn save_keybind( .map_err(|e| e.to_string())?; let _ = app_handle.track_event("keybind_saved", Some(serde_json::json!({ - "keybind": keybind_clone + "keybind": keybind }))); Ok(()) @@ -97,7 +94,7 @@ pub async fn get_keybind(app_handle: tauri::AppHandle) -> Result, St .map_err(|e| e.to_string())?; let json = row.map(|r| r.get::("value")).unwrap_or_else(|| { - serde_json::to_string(&vec!["Meta".to_string(), "V".to_string()]) + serde_json::to_string(&vec!["MetaLeft".to_string(), "KeyV".to_string()]) .expect("Failed to serialize default keybind") }); diff --git a/src-tauri/src/utils/keys.rs b/src-tauri/src/utils/keys.rs new file mode 100644 index 0000000..fffacdd --- /dev/null +++ b/src-tauri/src/utils/keys.rs @@ -0,0 +1,118 @@ +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/mod.rs b/src-tauri/src/utils/mod.rs index b888b1f..9554229 100644 --- a/src-tauri/src/utils/mod.rs +++ b/src-tauri/src/utils/mod.rs @@ -2,3 +2,4 @@ pub mod commands; pub mod favicon; pub mod types; pub mod logger; +pub mod keys; \ No newline at end of file diff --git a/types/keys.ts b/types/keys.ts new file mode 100644 index 0000000..d81454f --- /dev/null +++ b/types/keys.ts @@ -0,0 +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', +} \ No newline at end of file From c872490a9576e5a79d015bc2891634f9bfa68f3f Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Thu, 2 Jan 2025 17:10:09 +1000 Subject: [PATCH 041/110] feat: add redirect after saving keybind in settings.vue --- pages/settings.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/pages/settings.vue b/pages/settings.vue index 7a20eb1..52f84d3 100644 --- a/pages/settings.vue +++ b/pages/settings.vue @@ -131,6 +131,7 @@ const onKeyDown = (event: KeyboardEvent) => { const saveKeybind = async () => { if (keybind.value.length > 0) { await invoke("save_keybind", { keybind: keybind.value }); + router.push("/"); } else { showEmptyKeybindError.value = true; } From 80545504435ef5b1c55f32df6bff6318bccf3f97 Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Thu, 2 Jan 2025 17:10:46 +1000 Subject: [PATCH 042/110] fix: old hotkey not getting unregistered correctly --- src-tauri/src/api/hotkeys.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src-tauri/src/api/hotkeys.rs b/src-tauri/src/api/hotkeys.rs index 52a276b..69ee336 100644 --- a/src-tauri/src/api/hotkeys.rs +++ b/src-tauri/src/api/hotkeys.rs @@ -12,7 +12,7 @@ use tauri_plugin_aptabase::EventTracker; lazy_static! { static ref HOTKEY_MANAGER: Mutex> = Mutex::new(None); - static ref REGISTERED_HOTKEYS: Mutex> = Mutex::new(Vec::new()); + static ref REGISTERED_HOTKEY: Mutex> = Mutex::new(None); } pub fn setup(app_handle: tauri::AppHandle) { @@ -36,9 +36,6 @@ pub fn setup(app_handle: tauri::AppHandle) { .block_on(crate::db::settings::get_keybind(app_handle_clone.clone())) .expect("Failed to get initial keybind"); - let initial_shortcut_for_update = initial_keybind.clone(); - let initial_shortcut_for_save = initial_keybind.clone(); - if let Err(e) = register_shortcut(&initial_keybind) { eprintln!("Error registering initial shortcut: {:?}", e); } @@ -46,7 +43,7 @@ pub fn setup(app_handle: tauri::AppHandle) { app_handle.listen("update-shortcut", move |event| { let payload_str = event.payload(); - if let Ok(old_hotkey) = parse_hotkey(&initial_shortcut_for_update) { + if let Some(old_hotkey) = REGISTERED_HOTKEY.lock().unwrap().take() { let manager_guard = HOTKEY_MANAGER.lock().unwrap(); if let Some(manager) = manager_guard.as_ref() { let _ = manager.unregister(old_hotkey); @@ -63,7 +60,7 @@ pub fn setup(app_handle: tauri::AppHandle) { app_handle.listen("save_keybind", move |event| { let payload_str = event.payload().to_string(); - if let Ok(old_hotkey) = parse_hotkey(&initial_shortcut_for_save) { + if let Some(old_hotkey) = REGISTERED_HOTKEY.lock().unwrap().take() { let manager_guard = HOTKEY_MANAGER.lock().unwrap(); if let Some(manager) = manager_guard.as_ref() { let _ = manager.unregister(old_hotkey); @@ -100,7 +97,7 @@ fn register_shortcut(shortcut: &[String]) -> Result<(), Box Date: Thu, 2 Jan 2025 18:40:55 +1000 Subject: [PATCH 043/110] fix: spacing of main ui --- assets/css/index.scss | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/assets/css/index.scss b/assets/css/index.scss index 2fb355a..5feb44b 100644 --- a/assets/css/index.scss +++ b/assets/css/index.scss @@ -22,7 +22,7 @@ $mutedtext: #78756f; position: fixed; top: 0; left: 0; - height: 54px; + height: 56px; background-color: transparent; outline: none; border: none; @@ -35,10 +35,10 @@ $mutedtext: #78756f; .results { position: absolute; - width: 284px; - top: 53px; + width: 286px; + top: 55px; left: 0; - height: calc(100vh - 95px); + height: 417px; border-right: 1px solid $divider; display: flex; flex-direction: column; @@ -46,6 +46,7 @@ $mutedtext: #78756f; padding-bottom: 8px; overflow-y: auto; overflow-x: hidden; + z-index: 3; .result { height: 40px; @@ -59,6 +60,7 @@ $mutedtext: #78756f; overflow: hidden; text-overflow: clip; white-space: nowrap; + color: $text; } .result { @@ -96,20 +98,22 @@ $mutedtext: #78756f; .content { position: absolute; - top: 53px; - left: 284px; - height: calc(100vh - 254px); + top: 55px; + left: 285px; + height: 220px; font-family: CommitMono !important; font-size: 12px; letter-spacing: 1; border-radius: 10px; - width: calc(100vw - 286px); + width: 465px; white-space: pre-wrap; word-wrap: break-word; display: flex; flex-direction: column; align-items: center; overflow: hidden; + z-index: 2; + color: $text; &:not(:has(.image)) { padding: 8px; @@ -128,7 +132,7 @@ $mutedtext: #78756f; } .bottom-bar { - height: 40px; + height: 39px; width: calc(100vw - 2px); backdrop-filter: blur(18px); background-color: hsla(40, 3%, 16%, 0.8); @@ -215,18 +219,20 @@ $mutedtext: #78756f; display: flex; flex-direction: column; gap: 14px; - bottom: 40px; - left: 284px; + bottom: 39px; + left: 285px; height: 160px; - width: calc(100vw - 286px); + width: 465px; border-top: 1px solid $divider; background-color: $primary; padding: 14px; + z-index: 1; .title { font-family: SFRoundedSemiBold; font-size: 12px; letter-spacing: 0.6px; + color: $text; } .info-content { From 6d7874c1aef9605f189377d6959fb52ea405accb Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:41:10 +1000 Subject: [PATCH 044/110] feat: new settings ui --- assets/css/settings.scss | 133 ++++++++++++++++++++++++++++++--------- pages/settings.vue | 103 ++++++++++++++++++++++-------- 2 files changed, 179 insertions(+), 57 deletions(-) diff --git a/assets/css/settings.scss b/assets/css/settings.scss index 39bae81..70b1c53 100644 --- a/assets/css/settings.scss +++ b/assets/css/settings.scss @@ -36,49 +36,116 @@ $mutedtext: #78756f; } } -.keybind-container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100vh; - gap: 6px; - z-index: -1; +p { + font-family: SFRoundedMedium; +} - .title { - font-size: 20px; - font-weight: 800; - } +.settings-container { + width: 100%; + margin-top: 26px; + position: relative; + font-size: 12px; + font-family: SFRoundedMedium; - .keybind-input { - padding: 6px; - border: 1px solid $divider; - color: $text2; + .settings { + position: absolute; + left: 50%; + transform: translateX(-50%); + margin-left: -26px; display: flex; - border-radius: 13px; - outline: none; - gap: 6px; + gap: 24px; - .key { - color: $text2; - font-family: SFRoundedMedium; - background-color: $divider; - padding: 6px 8px; - border-radius: 8px; + .names { + display: flex; + flex-direction: column; + gap: 16px; + + p { + font-family: SFRoundedSemiBold; + color: $text2; + } + } + + .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; + } } } - .keybind-input:focus { - border: 1px solid rgba(255, 255, 255, 0.2); + .checkmark { + height: 14px; + width: 14px; + position: absolute; + opacity: 0; + transition: opacity 0.2s; } - &.empty-keybind { - .keybind-input { - border-color: rgba(255, 82, 82, 0.298); - } + 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%; + height: 56px; + border-bottom: 1px solid $divider; +} + .bottom-bar { height: 40px; width: calc(100vw - 2px); @@ -144,6 +211,10 @@ $mutedtext: #78756f; transition: all 0.2s; cursor: pointer; + p { + color: $text; + } + &.disabled { pointer-events: none; opacity: 0.5; diff --git a/pages/settings.vue b/pages/settings.vue index 52f84d3..d4814e0 100644 --- a/pages/settings.vue +++ b/pages/settings.vue @@ -1,9 +1,11 @@