mirror of
https://github.com/haexhub/haex-hub.git
synced 2025-12-19 07:20:50 +01:00
Compare commits
18 Commits
5ea04a80e0
...
v0.1.1
| Author | SHA1 | Date | |
|---|---|---|---|
| f727d00639 | |||
| a946b14f69 | |||
| 471baec284 | |||
| 8298d807f3 | |||
| 42e6459fbf | |||
| 6ae87fc694 | |||
| f7867a5bde | |||
| d82599f588 | |||
| 72bb211a76 | |||
| f14ce0d6ad | |||
| af09f4524d | |||
| 102832675d | |||
| 3490de2f51 | |||
| 7c3af10938 | |||
| 5c5d0785b9 | |||
| 121dd9dd00 | |||
| 4ff6aee4d8 | |||
| dceb49ae90 |
228
.github/workflows/build.yml
vendored
Normal file
228
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- develop
|
||||||
|
tags-ignore:
|
||||||
|
- '**'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- develop
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-desktop:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- platform: 'macos-latest'
|
||||||
|
args: '--target aarch64-apple-darwin'
|
||||||
|
- platform: 'macos-latest'
|
||||||
|
args: '--target x86_64-apple-darwin'
|
||||||
|
- platform: 'ubuntu-22.04'
|
||||||
|
args: ''
|
||||||
|
- platform: 'windows-latest'
|
||||||
|
args: ''
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.platform }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
|
||||||
|
- name: Setup Rust
|
||||||
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
|
||||||
|
|
||||||
|
- name: Install dependencies (Ubuntu)
|
||||||
|
if: matrix.platform == 'ubuntu-22.04'
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libssl-dev
|
||||||
|
|
||||||
|
- name: Get pnpm store directory
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Setup pnpm cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ${{ env.STORE_PATH }}
|
||||||
|
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-pnpm-store-
|
||||||
|
|
||||||
|
- name: Setup Rust cache
|
||||||
|
uses: Swatinem/rust-cache@v2
|
||||||
|
with:
|
||||||
|
workspaces: src-tauri
|
||||||
|
|
||||||
|
- name: Install frontend dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Build Tauri app
|
||||||
|
uses: tauri-apps/tauri-action@v0
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
args: ${{ matrix.args }}
|
||||||
|
|
||||||
|
- name: Upload artifacts (macOS)
|
||||||
|
if: matrix.platform == 'macos-latest'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: macos-${{ contains(matrix.args, 'aarch64') && 'aarch64' || 'x86_64' }}
|
||||||
|
path: |
|
||||||
|
src-tauri/target/*/release/bundle/dmg/*.dmg
|
||||||
|
src-tauri/target/*/release/bundle/macos/*.app
|
||||||
|
|
||||||
|
- name: Upload artifacts (Ubuntu)
|
||||||
|
if: matrix.platform == 'ubuntu-22.04'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: linux
|
||||||
|
path: |
|
||||||
|
src-tauri/target/release/bundle/deb/*.deb
|
||||||
|
src-tauri/target/release/bundle/appimage/*.AppImage
|
||||||
|
src-tauri/target/release/bundle/rpm/*.rpm
|
||||||
|
|
||||||
|
- name: Upload artifacts (Windows)
|
||||||
|
if: matrix.platform == 'windows-latest'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: windows
|
||||||
|
path: |
|
||||||
|
src-tauri/target/release/bundle/msi/*.msi
|
||||||
|
src-tauri/target/release/bundle/nsis/*.exe
|
||||||
|
|
||||||
|
build-android:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: '17'
|
||||||
|
|
||||||
|
- name: Setup Android SDK
|
||||||
|
uses: android-actions/setup-android@v3
|
||||||
|
|
||||||
|
- name: Setup Rust
|
||||||
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
|
- name: Install Rust Android targets
|
||||||
|
run: |
|
||||||
|
rustup target add aarch64-linux-android
|
||||||
|
rustup target add armv7-linux-androideabi
|
||||||
|
rustup target add i686-linux-android
|
||||||
|
rustup target add x86_64-linux-android
|
||||||
|
|
||||||
|
- name: Setup NDK
|
||||||
|
uses: nttld/setup-ndk@v1
|
||||||
|
with:
|
||||||
|
ndk-version: r26d
|
||||||
|
id: setup-ndk
|
||||||
|
|
||||||
|
- name: Setup Android NDK environment for OpenSSL
|
||||||
|
run: |
|
||||||
|
echo "ANDROID_NDK_HOME=${{ steps.setup-ndk.outputs.ndk-path }}" >> $GITHUB_ENV
|
||||||
|
echo "NDK_HOME=${{ steps.setup-ndk.outputs.ndk-path }}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# Add all Android toolchains to PATH for OpenSSL cross-compilation
|
||||||
|
echo "${{ steps.setup-ndk.outputs.ndk-path }}/toolchains/llvm/prebuilt/linux-x86_64/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
# Set CC, AR, RANLIB for each target
|
||||||
|
echo "CC_aarch64_linux_android=aarch64-linux-android24-clang" >> $GITHUB_ENV
|
||||||
|
echo "AR_aarch64_linux_android=llvm-ar" >> $GITHUB_ENV
|
||||||
|
echo "RANLIB_aarch64_linux_android=llvm-ranlib" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
echo "CC_armv7_linux_androideabi=armv7a-linux-androideabi24-clang" >> $GITHUB_ENV
|
||||||
|
echo "AR_armv7_linux_androideabi=llvm-ar" >> $GITHUB_ENV
|
||||||
|
echo "RANLIB_armv7_linux_androideabi=llvm-ranlib" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
echo "CC_i686_linux_android=i686-linux-android24-clang" >> $GITHUB_ENV
|
||||||
|
echo "AR_i686_linux_android=llvm-ar" >> $GITHUB_ENV
|
||||||
|
echo "RANLIB_i686_linux_android=llvm-ranlib" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
echo "CC_x86_64_linux_android=x86_64-linux-android24-clang" >> $GITHUB_ENV
|
||||||
|
echo "AR_x86_64_linux_android=llvm-ar" >> $GITHUB_ENV
|
||||||
|
echo "RANLIB_x86_64_linux_android=llvm-ranlib" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Install build dependencies for OpenSSL
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y perl make
|
||||||
|
|
||||||
|
- name: Get pnpm store directory
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Setup pnpm cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ${{ env.STORE_PATH }}
|
||||||
|
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-pnpm-store-
|
||||||
|
|
||||||
|
- name: Setup Rust cache
|
||||||
|
uses: Swatinem/rust-cache@v2
|
||||||
|
with:
|
||||||
|
workspaces: src-tauri
|
||||||
|
|
||||||
|
- name: Install frontend dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Setup Keystore (if secrets available)
|
||||||
|
env:
|
||||||
|
ANDROID_KEYSTORE: ${{ secrets.ANDROID_KEYSTORE }}
|
||||||
|
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
|
||||||
|
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
|
||||||
|
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
if [ -n "$ANDROID_KEYSTORE" ]; then
|
||||||
|
echo "$ANDROID_KEYSTORE" | base64 -d > $HOME/keystore.jks
|
||||||
|
echo "ANDROID_KEYSTORE_PATH=$HOME/keystore.jks" >> $GITHUB_ENV
|
||||||
|
echo "ANDROID_KEYSTORE_PASSWORD=$ANDROID_KEYSTORE_PASSWORD" >> $GITHUB_ENV
|
||||||
|
echo "ANDROID_KEY_ALIAS=$ANDROID_KEY_ALIAS" >> $GITHUB_ENV
|
||||||
|
echo "ANDROID_KEY_PASSWORD=$ANDROID_KEY_PASSWORD" >> $GITHUB_ENV
|
||||||
|
echo "Keystore configured for signing"
|
||||||
|
else
|
||||||
|
echo "No keystore configured, building unsigned APK"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build Android APK and AAB (unsigned if no keystore)
|
||||||
|
run: pnpm tauri android build
|
||||||
|
|
||||||
|
- name: Upload Android artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: android
|
||||||
|
path: |
|
||||||
|
src-tauri/gen/android/app/build/outputs/apk/**/*.apk
|
||||||
|
src-tauri/gen/android/app/build/outputs/bundle/**/*.aab
|
||||||
251
.github/workflows/release.yml
vendored
Normal file
251
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
create-release:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
outputs:
|
||||||
|
release_id: ${{ steps.create-release.outputs.release_id }}
|
||||||
|
upload_url: ${{ steps.create-release.outputs.upload_url }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
|
||||||
|
- name: Get version
|
||||||
|
run: echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
id: create-release
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const { data } = await github.rest.repos.createRelease({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
tag_name: `v${process.env.PACKAGE_VERSION}`,
|
||||||
|
name: `haex-hub v${process.env.PACKAGE_VERSION}`,
|
||||||
|
body: 'Take a look at the assets to download and install this app.',
|
||||||
|
draft: true,
|
||||||
|
prerelease: false
|
||||||
|
})
|
||||||
|
core.setOutput('release_id', data.id)
|
||||||
|
core.setOutput('upload_url', data.upload_url)
|
||||||
|
return data.id
|
||||||
|
|
||||||
|
build-desktop:
|
||||||
|
needs: create-release
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- platform: 'macos-latest'
|
||||||
|
args: '--target aarch64-apple-darwin'
|
||||||
|
- platform: 'macos-latest'
|
||||||
|
args: '--target x86_64-apple-darwin'
|
||||||
|
- platform: 'ubuntu-22.04'
|
||||||
|
args: ''
|
||||||
|
- platform: 'windows-latest'
|
||||||
|
args: ''
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.platform }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
|
||||||
|
- name: Setup Rust
|
||||||
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
|
||||||
|
|
||||||
|
- name: Install dependencies (Ubuntu)
|
||||||
|
if: matrix.platform == 'ubuntu-22.04'
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libssl-dev
|
||||||
|
|
||||||
|
- name: Get pnpm store directory
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Setup pnpm cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ${{ env.STORE_PATH }}
|
||||||
|
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-pnpm-store-
|
||||||
|
|
||||||
|
- name: Setup Rust cache
|
||||||
|
uses: Swatinem/rust-cache@v2
|
||||||
|
with:
|
||||||
|
workspaces: src-tauri
|
||||||
|
|
||||||
|
- name: Install frontend dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Build and release Tauri app
|
||||||
|
uses: tauri-apps/tauri-action@v0
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
releaseId: ${{ needs.create-release.outputs.release_id }}
|
||||||
|
args: ${{ matrix.args }}
|
||||||
|
|
||||||
|
build-android:
|
||||||
|
needs: create-release
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: '17'
|
||||||
|
|
||||||
|
- name: Setup Android SDK
|
||||||
|
uses: android-actions/setup-android@v3
|
||||||
|
|
||||||
|
- name: Setup Rust
|
||||||
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
|
- name: Install Rust Android targets
|
||||||
|
run: |
|
||||||
|
rustup target add aarch64-linux-android
|
||||||
|
rustup target add armv7-linux-androideabi
|
||||||
|
rustup target add i686-linux-android
|
||||||
|
rustup target add x86_64-linux-android
|
||||||
|
|
||||||
|
- name: Setup NDK
|
||||||
|
uses: nttld/setup-ndk@v1
|
||||||
|
with:
|
||||||
|
ndk-version: r26d
|
||||||
|
id: setup-ndk
|
||||||
|
|
||||||
|
- name: Setup Android NDK environment for OpenSSL
|
||||||
|
run: |
|
||||||
|
echo "ANDROID_NDK_HOME=${{ steps.setup-ndk.outputs.ndk-path }}" >> $GITHUB_ENV
|
||||||
|
echo "NDK_HOME=${{ steps.setup-ndk.outputs.ndk-path }}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# Add all Android toolchains to PATH for OpenSSL cross-compilation
|
||||||
|
echo "${{ steps.setup-ndk.outputs.ndk-path }}/toolchains/llvm/prebuilt/linux-x86_64/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
# Set CC, AR, RANLIB for each target
|
||||||
|
echo "CC_aarch64_linux_android=aarch64-linux-android24-clang" >> $GITHUB_ENV
|
||||||
|
echo "AR_aarch64_linux_android=llvm-ar" >> $GITHUB_ENV
|
||||||
|
echo "RANLIB_aarch64_linux_android=llvm-ranlib" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
echo "CC_armv7_linux_androideabi=armv7a-linux-androideabi24-clang" >> $GITHUB_ENV
|
||||||
|
echo "AR_armv7_linux_androideabi=llvm-ar" >> $GITHUB_ENV
|
||||||
|
echo "RANLIB_armv7_linux_androideabi=llvm-ranlib" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
echo "CC_i686_linux_android=i686-linux-android24-clang" >> $GITHUB_ENV
|
||||||
|
echo "AR_i686_linux_android=llvm-ar" >> $GITHUB_ENV
|
||||||
|
echo "RANLIB_i686_linux_android=llvm-ranlib" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
echo "CC_x86_64_linux_android=x86_64-linux-android24-clang" >> $GITHUB_ENV
|
||||||
|
echo "AR_x86_64_linux_android=llvm-ar" >> $GITHUB_ENV
|
||||||
|
echo "RANLIB_x86_64_linux_android=llvm-ranlib" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Install build dependencies for OpenSSL
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y perl make
|
||||||
|
|
||||||
|
- name: Get pnpm store directory
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Setup pnpm cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ${{ env.STORE_PATH }}
|
||||||
|
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-pnpm-store-
|
||||||
|
|
||||||
|
- name: Setup Rust cache
|
||||||
|
uses: Swatinem/rust-cache@v2
|
||||||
|
with:
|
||||||
|
workspaces: src-tauri
|
||||||
|
|
||||||
|
- name: Install frontend dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Setup Keystore (required for release)
|
||||||
|
run: |
|
||||||
|
echo "${{ secrets.ANDROID_KEYSTORE }}" | base64 -d > $HOME/keystore.jks
|
||||||
|
echo "ANDROID_KEYSTORE_PATH=$HOME/keystore.jks" >> $GITHUB_ENV
|
||||||
|
echo "ANDROID_KEYSTORE_PASSWORD=${{ secrets.ANDROID_KEYSTORE_PASSWORD }}" >> $GITHUB_ENV
|
||||||
|
echo "ANDROID_KEY_ALIAS=${{ secrets.ANDROID_KEY_ALIAS }}" >> $GITHUB_ENV
|
||||||
|
echo "ANDROID_KEY_PASSWORD=${{ secrets.ANDROID_KEY_PASSWORD }}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Build Android APK and AAB (signed)
|
||||||
|
run: pnpm tauri android build
|
||||||
|
|
||||||
|
- name: Upload Android artifacts to Release
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
gh release upload ${{ github.ref_name }} \
|
||||||
|
src-tauri/gen/android/app/build/outputs/apk/universal/release/app-universal-release.apk \
|
||||||
|
src-tauri/gen/android/app/build/outputs/bundle/universalRelease/app-universal-release.aab \
|
||||||
|
--clobber
|
||||||
|
|
||||||
|
publish-release:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
needs: [create-release, build-desktop, build-android]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Publish release
|
||||||
|
id: publish-release
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
env:
|
||||||
|
release_id: ${{ needs.create-release.outputs.release_id }}
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
github.rest.repos.updateRelease({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
release_id: process.env.release_id,
|
||||||
|
draft: false,
|
||||||
|
prerelease: false
|
||||||
|
})
|
||||||
13
CLAUDE.md
13
CLAUDE.md
@ -1,13 +0,0 @@
|
|||||||
# Verwandte Projekte
|
|
||||||
|
|
||||||
## SDK
|
|
||||||
|
|
||||||
- /home/haex/Projekte/haexhub-sdk
|
|
||||||
|
|
||||||
## Erweiterung HaexPass (Password Manager)
|
|
||||||
|
|
||||||
- /home/haex/Projekte/haex-pass
|
|
||||||
|
|
||||||
# Codingstyle
|
|
||||||
|
|
||||||
- alle asynchronen Funktionen bitte mit Async prependen
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "haex-hub",
|
"name": "haex-hub",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "nuxt build",
|
"build": "nuxt build",
|
||||||
|
|||||||
108
src-tauri/Cargo.lock
generated
108
src-tauri/Cargo.lock
generated
@ -1715,6 +1715,7 @@ dependencies = [
|
|||||||
"tauri-plugin-persisted-scope",
|
"tauri-plugin-persisted-scope",
|
||||||
"tauri-plugin-store",
|
"tauri-plugin-store",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.17",
|
||||||
|
"trash",
|
||||||
"ts-rs",
|
"ts-rs",
|
||||||
"uhlc",
|
"uhlc",
|
||||||
"url",
|
"url",
|
||||||
@ -4431,7 +4432,7 @@ dependencies = [
|
|||||||
"tao-macros",
|
"tao-macros",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"url",
|
"url",
|
||||||
"windows",
|
"windows 0.61.1",
|
||||||
"windows-core 0.61.0",
|
"windows-core 0.61.0",
|
||||||
"windows-version",
|
"windows-version",
|
||||||
"x11-dl",
|
"x11-dl",
|
||||||
@ -4503,7 +4504,7 @@ dependencies = [
|
|||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"window-vibrancy",
|
"window-vibrancy",
|
||||||
"windows",
|
"windows 0.61.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4687,7 +4688,7 @@ dependencies = [
|
|||||||
"tauri-plugin",
|
"tauri-plugin",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.17",
|
||||||
"url",
|
"url",
|
||||||
"windows",
|
"windows 0.61.1",
|
||||||
"zbus",
|
"zbus",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -4763,7 +4764,7 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"windows",
|
"windows 0.61.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4789,7 +4790,7 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"windows",
|
"windows 0.61.1",
|
||||||
"wry",
|
"wry",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -4849,7 +4850,7 @@ checksum = "0b1e66e07de489fe43a46678dd0b8df65e0c973909df1b60ba33874e297ba9b9"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"quick-xml 0.37.5",
|
"quick-xml 0.37.5",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.17",
|
||||||
"windows",
|
"windows 0.61.1",
|
||||||
"windows-version",
|
"windows-version",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -5189,6 +5190,24 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "trash"
|
||||||
|
version = "5.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22746c6b0c6d85d60a8f0d858f7057dfdf11297c132679f452ec908fba42b871"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"objc2 0.5.2",
|
||||||
|
"objc2-foundation 0.2.2",
|
||||||
|
"once_cell",
|
||||||
|
"percent-encoding",
|
||||||
|
"scopeguard",
|
||||||
|
"urlencoding",
|
||||||
|
"windows 0.56.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tray-icon"
|
name = "tray-icon"
|
||||||
version = "0.21.0"
|
version = "0.21.0"
|
||||||
@ -5353,6 +5372,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "urlencoding"
|
||||||
|
version = "2.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "urlpattern"
|
name = "urlpattern"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -5638,10 +5663,10 @@ checksum = "d4ba622a989277ef3886dd5afb3e280e3dd6d974b766118950a08f8f678ad6a4"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"webview2-com-macros",
|
"webview2-com-macros",
|
||||||
"webview2-com-sys",
|
"webview2-com-sys",
|
||||||
"windows",
|
"windows 0.61.1",
|
||||||
"windows-core 0.61.0",
|
"windows-core 0.61.0",
|
||||||
"windows-implement",
|
"windows-implement 0.60.0",
|
||||||
"windows-interface",
|
"windows-interface 0.59.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5662,7 +5687,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "36695906a1b53a3bf5c4289621efedac12b73eeb0b89e7e1a89b517302d5d75c"
|
checksum = "36695906a1b53a3bf5c4289621efedac12b73eeb0b89e7e1a89b517302d5d75c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.17",
|
||||||
"windows",
|
"windows 0.61.1",
|
||||||
"windows-core 0.61.0",
|
"windows-core 0.61.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -5712,6 +5737,16 @@ dependencies = [
|
|||||||
"windows-version",
|
"windows-version",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows"
|
||||||
|
version = "0.56.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core 0.56.0",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows"
|
name = "windows"
|
||||||
version = "0.61.1"
|
version = "0.61.1"
|
||||||
@ -5743,16 +5778,28 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.56.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6"
|
||||||
|
dependencies = [
|
||||||
|
"windows-implement 0.56.0",
|
||||||
|
"windows-interface 0.56.0",
|
||||||
|
"windows-result 0.1.2",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.61.0"
|
version = "0.61.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
|
checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-implement",
|
"windows-implement 0.60.0",
|
||||||
"windows-interface",
|
"windows-interface 0.59.1",
|
||||||
"windows-link",
|
"windows-link",
|
||||||
"windows-result",
|
"windows-result 0.3.2",
|
||||||
"windows-strings 0.4.0",
|
"windows-strings 0.4.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -5766,6 +5813,17 @@ dependencies = [
|
|||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-implement"
|
||||||
|
version = "0.56.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.100",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-implement"
|
name = "windows-implement"
|
||||||
version = "0.60.0"
|
version = "0.60.0"
|
||||||
@ -5777,6 +5835,17 @@ dependencies = [
|
|||||||
"syn 2.0.100",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-interface"
|
||||||
|
version = "0.56.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.100",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-interface"
|
name = "windows-interface"
|
||||||
version = "0.59.1"
|
version = "0.59.1"
|
||||||
@ -5810,11 +5879,20 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3"
|
checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-result",
|
"windows-result 0.3.2",
|
||||||
"windows-strings 0.3.1",
|
"windows-strings 0.3.1",
|
||||||
"windows-targets 0.53.2",
|
"windows-targets 0.53.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-result"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-result"
|
name = "windows-result"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
@ -6226,7 +6304,7 @@ dependencies = [
|
|||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webkit2gtk-sys",
|
"webkit2gtk-sys",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"windows",
|
"windows 0.61.1",
|
||||||
"windows-core 0.61.0",
|
"windows-core 0.61.0",
|
||||||
"windows-version",
|
"windows-version",
|
||||||
"x11-dl",
|
"x11-dl",
|
||||||
|
|||||||
@ -20,13 +20,8 @@ tauri-build = { version = "2.2", features = [] }
|
|||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rusqlite = { version = "0.37.0", features = [
|
tokio = { version = "1.47.1", features = ["macros", "rt-multi-thread"] }
|
||||||
"load_extension",
|
#libsqlite3-sys = { version = "0.31", features = ["bundled-sqlcipher"] }
|
||||||
"bundled-sqlcipher-vendored-openssl",
|
|
||||||
"functions",
|
|
||||||
] }
|
|
||||||
|
|
||||||
#tauri-plugin-sql = { version = "2", features = ["sqlite"] }tokio = { version = "1.47.1", features = ["macros", "rt-multi-thread"] }#libsqlite3-sys = { version = "0.31", features = ["bundled-sqlcipher"] }
|
|
||||||
#sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "sqlite"] }
|
#sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "sqlite"] }
|
||||||
base64 = "0.22"
|
base64 = "0.22"
|
||||||
ed25519-dalek = "2.1"
|
ed25519-dalek = "2.1"
|
||||||
@ -54,3 +49,10 @@ uhlc = "0.8.2"
|
|||||||
url = "2.5.7"
|
url = "2.5.7"
|
||||||
uuid = { version = "1.18.1", features = ["v4"] }
|
uuid = { version = "1.18.1", features = ["v4"] }
|
||||||
zip = "6.0.0"
|
zip = "6.0.0"
|
||||||
|
|
||||||
|
[target.'cfg(not(target_os = "android"))'.dependencies]
|
||||||
|
trash = "5.2.0"
|
||||||
|
rusqlite = { version = "0.37.0", features = ["load_extension", "bundled-sqlcipher-vendored-openssl", "functions"] }
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "android")'.dependencies]
|
||||||
|
rusqlite = { version = "0.37.0", features = ["load_extension", "bundled-sqlcipher-vendored-openssl", "functions"] }
|
||||||
|
|||||||
@ -24,6 +24,23 @@ android {
|
|||||||
versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt()
|
versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt()
|
||||||
versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0")
|
versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signingConfigs {
|
||||||
|
create("release") {
|
||||||
|
val keystorePath = System.getenv("ANDROID_KEYSTORE_PATH")
|
||||||
|
val keystorePassword = System.getenv("ANDROID_KEYSTORE_PASSWORD")
|
||||||
|
val keyAlias = System.getenv("ANDROID_KEY_ALIAS")
|
||||||
|
val keyPassword = System.getenv("ANDROID_KEY_PASSWORD")
|
||||||
|
|
||||||
|
if (keystorePath != null && keystorePassword != null && keyAlias != null && keyPassword != null) {
|
||||||
|
storeFile = file(keystorePath)
|
||||||
|
storePassword = keystorePassword
|
||||||
|
this.keyAlias = keyAlias
|
||||||
|
this.keyPassword = keyPassword
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
getByName("debug") {
|
getByName("debug") {
|
||||||
manifestPlaceholders["usesCleartextTraffic"] = "true"
|
manifestPlaceholders["usesCleartextTraffic"] = "true"
|
||||||
@ -43,6 +60,12 @@ android {
|
|||||||
.plus(getDefaultProguardFile("proguard-android-optimize.txt"))
|
.plus(getDefaultProguardFile("proguard-android-optimize.txt"))
|
||||||
.toList().toTypedArray()
|
.toList().toTypedArray()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Sign with release config if available
|
||||||
|
val releaseSigningConfig = signingConfigs.getByName("release")
|
||||||
|
if (releaseSigningConfig.storeFile != null) {
|
||||||
|
signingConfig = releaseSigningConfig
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
|
|||||||
Binary file not shown.
@ -20,6 +20,8 @@ use std::time::UNIX_EPOCH;
|
|||||||
use std::{fs, sync::Arc};
|
use std::{fs, sync::Arc};
|
||||||
use tauri::{path::BaseDirectory, AppHandle, Manager, State};
|
use tauri::{path::BaseDirectory, AppHandle, Manager, State};
|
||||||
use tauri_plugin_fs::FsExt;
|
use tauri_plugin_fs::FsExt;
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
|
use trash;
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
|
|
||||||
pub struct DbConnection(pub Arc<Mutex<Option<Connection>>>);
|
pub struct DbConnection(pub Arc<Mutex<Option<Connection>>>);
|
||||||
@ -212,7 +214,60 @@ pub fn vault_exists(app_handle: AppHandle, vault_name: String) -> Result<bool, D
|
|||||||
Ok(Path::new(&vault_path).exists())
|
Ok(Path::new(&vault_path).exists())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes a vault database file
|
/// Moves a vault database file to trash (or deletes permanently if trash is unavailable)
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn move_vault_to_trash(
|
||||||
|
app_handle: AppHandle,
|
||||||
|
vault_name: String,
|
||||||
|
) -> Result<String, DatabaseError> {
|
||||||
|
// On Android, trash is not available, so delete permanently
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
{
|
||||||
|
println!(
|
||||||
|
"Android platform detected, permanently deleting vault '{}'",
|
||||||
|
vault_name
|
||||||
|
);
|
||||||
|
return delete_vault(app_handle, vault_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// On non-Android platforms, try to use trash
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
|
{
|
||||||
|
let vault_path = get_vault_path(&app_handle, &vault_name)?;
|
||||||
|
let vault_shm_path = format!("{}-shm", vault_path);
|
||||||
|
let vault_wal_path = format!("{}-wal", vault_path);
|
||||||
|
|
||||||
|
if !Path::new(&vault_path).exists() {
|
||||||
|
return Err(DatabaseError::IoError {
|
||||||
|
path: vault_path,
|
||||||
|
reason: "Vault does not exist".to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to move to trash first (works on desktop systems)
|
||||||
|
let moved_to_trash = trash::delete(&vault_path).is_ok();
|
||||||
|
|
||||||
|
if moved_to_trash {
|
||||||
|
// Also try to move auxiliary files to trash (ignore errors as they might not exist)
|
||||||
|
let _ = trash::delete(&vault_shm_path);
|
||||||
|
let _ = trash::delete(&vault_wal_path);
|
||||||
|
|
||||||
|
Ok(format!(
|
||||||
|
"Vault '{}' successfully moved to trash",
|
||||||
|
vault_name
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
// Fallback: Permanent deletion if trash fails
|
||||||
|
println!(
|
||||||
|
"Trash not available, falling back to permanent deletion for vault '{}'",
|
||||||
|
vault_name
|
||||||
|
);
|
||||||
|
delete_vault(app_handle, vault_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deletes a vault database file permanently (bypasses trash)
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn delete_vault(app_handle: AppHandle, vault_name: String) -> Result<String, DatabaseError> {
|
pub fn delete_vault(app_handle: AppHandle, vault_name: String) -> Result<String, DatabaseError> {
|
||||||
let vault_path = get_vault_path(&app_handle, &vault_name)?;
|
let vault_path = get_vault_path(&app_handle, &vault_name)?;
|
||||||
|
|||||||
@ -68,6 +68,7 @@ pub fn run() {
|
|||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
database::create_encrypted_database,
|
database::create_encrypted_database,
|
||||||
database::delete_vault,
|
database::delete_vault,
|
||||||
|
database::move_vault_to_trash,
|
||||||
database::list_vaults,
|
database::list_vaults,
|
||||||
database::open_encrypted_database,
|
database::open_encrypted_database,
|
||||||
database::sql_execute_with_crdt,
|
database::sql_execute_with_crdt,
|
||||||
|
|||||||
@ -1,5 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<UPopover v-model:open="open">
|
<UDrawer
|
||||||
|
v-model:open="open"
|
||||||
|
direction="right"
|
||||||
|
:title="t('launcher.title')"
|
||||||
|
:description="t('launcher.description')"
|
||||||
|
:ui="{
|
||||||
|
content: 'w-dvw max-w-md sm:max-w-fit',
|
||||||
|
}"
|
||||||
|
>
|
||||||
<UButton
|
<UButton
|
||||||
icon="material-symbols:apps"
|
icon="material-symbols:apps"
|
||||||
color="neutral"
|
color="neutral"
|
||||||
@ -9,7 +17,8 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<template #content>
|
<template #content>
|
||||||
<ul class="p-4 max-h-96 grid grid-cols-3 gap-2 overflow-scroll">
|
<div class="p-4 h-full overflow-y-auto">
|
||||||
|
<div class="flex flex-wrap">
|
||||||
<!-- All launcher items (system windows + enabled extensions, alphabetically sorted) -->
|
<!-- All launcher items (system windows + enabled extensions, alphabetically sorted) -->
|
||||||
<UContextMenu
|
<UContextMenu
|
||||||
v-for="item in launcherItems"
|
v-for="item in launcherItems"
|
||||||
@ -52,15 +61,20 @@
|
|||||||
:label="extension.name"
|
:label="extension.name"
|
||||||
:tooltip="`${extension.name} (${t('disabled')})`"
|
:tooltip="`${extension.name} (${t('disabled')})`"
|
||||||
/>
|
/>
|
||||||
</ul>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</UPopover>
|
</UDrawer>
|
||||||
|
|
||||||
<!-- Uninstall Confirmation Dialog -->
|
<!-- Uninstall Confirmation Dialog -->
|
||||||
<UiDialogConfirm
|
<UiDialogConfirm
|
||||||
v-model:open="showUninstallDialog"
|
v-model:open="showUninstallDialog"
|
||||||
:title="t('uninstall.confirm.title')"
|
:title="t('uninstall.confirm.title')"
|
||||||
:description="t('uninstall.confirm.description', { name: extensionToUninstall?.name || '' })"
|
:description="
|
||||||
|
t('uninstall.confirm.description', {
|
||||||
|
name: extensionToUninstall?.name || '',
|
||||||
|
})
|
||||||
|
"
|
||||||
:confirm-label="t('uninstall.confirm.button')"
|
:confirm-label="t('uninstall.confirm.button')"
|
||||||
confirm-icon="i-heroicons-trash"
|
confirm-icon="i-heroicons-trash"
|
||||||
@confirm="confirmUninstall"
|
@confirm="confirmUninstall"
|
||||||
@ -237,6 +251,9 @@ const handleDragEnd = () => {
|
|||||||
de:
|
de:
|
||||||
disabled: Deaktiviert
|
disabled: Deaktiviert
|
||||||
marketplace: Marketplace
|
marketplace: Marketplace
|
||||||
|
launcher:
|
||||||
|
title: App Launcher
|
||||||
|
description: Wähle eine App zum Öffnen
|
||||||
contextMenu:
|
contextMenu:
|
||||||
open: Öffnen
|
open: Öffnen
|
||||||
uninstall: Deinstallieren
|
uninstall: Deinstallieren
|
||||||
@ -249,6 +266,9 @@ de:
|
|||||||
en:
|
en:
|
||||||
disabled: Disabled
|
disabled: Disabled
|
||||||
marketplace: Marketplace
|
marketplace: Marketplace
|
||||||
|
launcher:
|
||||||
|
title: App Launcher
|
||||||
|
description: Select an app to open
|
||||||
contextMenu:
|
contextMenu:
|
||||||
open: Open
|
open: Open
|
||||||
uninstall: Uninstall
|
uninstall: Uninstall
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
<UiDialogConfirm
|
<UiDialogConfirm
|
||||||
:confirm-label="t('create')"
|
:confirm-label="t('create')"
|
||||||
@confirm="onCreateAsync"
|
@confirm="onCreateAsync"
|
||||||
|
:description="t('description')"
|
||||||
>
|
>
|
||||||
<UiButton
|
<UiButton
|
||||||
:label="t('vault.create')"
|
:label="t('vault.create')"
|
||||||
@ -55,7 +56,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { vaultSchema } from './schema'
|
import { vaultSchema } from './schema'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n({
|
||||||
|
useScope: 'local',
|
||||||
|
})
|
||||||
|
|
||||||
const vault = reactive<{
|
const vault = reactive<{
|
||||||
name: string
|
name: string
|
||||||
@ -118,6 +121,7 @@ de:
|
|||||||
name: HaexVault
|
name: HaexVault
|
||||||
title: Neue {haexvault} erstellen
|
title: Neue {haexvault} erstellen
|
||||||
create: Erstellen
|
create: Erstellen
|
||||||
|
description: Erstelle eine neue Vault für deine Daten
|
||||||
|
|
||||||
en:
|
en:
|
||||||
vault:
|
vault:
|
||||||
@ -127,4 +131,5 @@ en:
|
|||||||
name: HaexVault
|
name: HaexVault
|
||||||
title: Create new {haexvault}
|
title: Create new {haexvault}
|
||||||
create: Create
|
create: Create
|
||||||
|
description: Create a new vault for your data
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|||||||
@ -58,7 +58,9 @@ const props = defineProps<{
|
|||||||
path?: string
|
path?: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n({
|
||||||
|
useScope: 'local',
|
||||||
|
})
|
||||||
|
|
||||||
const vault = reactive<{
|
const vault = reactive<{
|
||||||
name: string
|
name: string
|
||||||
|
|||||||
@ -1,27 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<UModal
|
<UDrawer
|
||||||
v-model:open="localShowWindowOverview"
|
v-model:open="localShowWindowOverview"
|
||||||
|
direction="bottom"
|
||||||
:title="t('modal.title')"
|
:title="t('modal.title')"
|
||||||
:description="t('modal.description')"
|
:description="t('modal.description')"
|
||||||
fullscreen
|
|
||||||
>
|
>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="flex flex-col h-full">
|
<div class="h-full overflow-y-auto p-6 justify-center flex">
|
||||||
<!-- Header -->
|
|
||||||
<div
|
|
||||||
class="flex items-center justify-end border-b p-2 border-gray-200 dark:border-gray-700"
|
|
||||||
>
|
|
||||||
<UButton
|
|
||||||
icon="i-heroicons-x-mark"
|
|
||||||
color="error"
|
|
||||||
variant="soft"
|
|
||||||
@click="localShowWindowOverview = false"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Scrollable Content -->
|
|
||||||
<div class="flex-1 overflow-y-auto p-6 justify-center flex">
|
|
||||||
<!-- Window Thumbnails Flex Layout -->
|
<!-- Window Thumbnails Flex Layout -->
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="windows.length > 0"
|
v-if="windows.length > 0"
|
||||||
class="flex flex-wrap gap-6 justify-center-safe items-start"
|
class="flex flex-wrap gap-6 justify-center-safe items-start"
|
||||||
@ -82,9 +69,8 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</UModal>
|
</UDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|||||||
28
src/components/ui/button/context.vue
Normal file
28
src/components/ui/button/context.vue
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<template>
|
||||||
|
<UContextMenu :items="contextMenuItems">
|
||||||
|
<UiButton
|
||||||
|
v-bind="$attrs"
|
||||||
|
@click="$emit('click', $event)"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
v-for="(_, slotName) in $slots"
|
||||||
|
#[slotName]="slotProps"
|
||||||
|
>
|
||||||
|
<slot
|
||||||
|
:name="slotName"
|
||||||
|
v-bind="slotProps"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</UiButton>
|
||||||
|
</UContextMenu>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ContextMenuItem } from '@nuxt/ui'
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
contextMenuItems: ContextMenuItem[]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
defineEmits<{ click: [Event] }>()
|
||||||
|
</script>
|
||||||
@ -4,11 +4,10 @@
|
|||||||
<UButton
|
<UButton
|
||||||
class="pointer-events-auto"
|
class="pointer-events-auto"
|
||||||
v-bind="{
|
v-bind="{
|
||||||
...{ size: isSmallScreen ? 'lg' : 'md' },
|
|
||||||
...buttonProps,
|
...buttonProps,
|
||||||
...$attrs,
|
...$attrs,
|
||||||
}"
|
}"
|
||||||
@click="(e) => $emit('click', e)"
|
@click="$emit('click', $event)"
|
||||||
>
|
>
|
||||||
<template
|
<template
|
||||||
v-for="(_, slotName) in $slots"
|
v-for="(_, slotName) in $slots"
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-full h-full flex flex-col">
|
<div class="w-full h-dvh flex flex-col">
|
||||||
<UPageHeader
|
<UPageHeader
|
||||||
ref="headerEl"
|
ref="headerEl"
|
||||||
as="header"
|
as="header"
|
||||||
@ -25,7 +25,7 @@
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
icon="i-bi-person-workspace"
|
icon="i-bi-person-workspace"
|
||||||
size="lg"
|
size="lg"
|
||||||
:tooltip="t('header.workspaces')"
|
:tooltip="t('workspaces.label')"
|
||||||
@click="isOverviewMode = !isOverviewMode"
|
@click="isOverviewMode = !isOverviewMode"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -54,7 +54,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</UPageHeader>
|
</UPageHeader>
|
||||||
|
|
||||||
<main class="flex-1 overflow-hidden bg-elevated flex flex-col relative">
|
<main class="overflow-hidden relative bg-elevated h-full">
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
@ -95,7 +95,7 @@
|
|||||||
class="mt-6"
|
class="mt-6"
|
||||||
@click="handleAddWorkspace"
|
@click="handleAddWorkspace"
|
||||||
icon="i-heroicons-plus"
|
icon="i-heroicons-plus"
|
||||||
:label="t('add')"
|
:label="t('workspaces.add')"
|
||||||
>
|
>
|
||||||
</UButton>
|
</UButton>
|
||||||
</div>
|
</div>
|
||||||
@ -142,14 +142,14 @@ de:
|
|||||||
search:
|
search:
|
||||||
label: Suche
|
label: Suche
|
||||||
|
|
||||||
header:
|
workspaces:
|
||||||
workspaces: Workspaces
|
label: Workspaces
|
||||||
add: Workspace hinzufügen
|
add: Workspace hinzufügen
|
||||||
en:
|
en:
|
||||||
search:
|
search:
|
||||||
label: Search
|
label: Search
|
||||||
|
|
||||||
header:
|
workspaces:
|
||||||
workspaces: Workspaces
|
label: Workspaces
|
||||||
add: Add Workspace
|
add: Add Workspace
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|||||||
@ -1,23 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="h-full">
|
||||||
<NuxtLayout>
|
<NuxtLayout>
|
||||||
<UDashboardPanel
|
|
||||||
id="inbox-1"
|
|
||||||
resizable
|
|
||||||
class=""
|
|
||||||
>
|
|
||||||
<template #body>
|
|
||||||
<div class="items-center justify-center flex relative flex-1">
|
|
||||||
<!-- <div class="absolute top-0 right-0">
|
|
||||||
<UiDropdownLocale @select="onSelectLocale" />
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="flex flex-col justify-center items-center gap-5 max-w-3xl"
|
class="flex flex-col justify-center items-center gap-5 mx-auto h-full overflow-scroll"
|
||||||
>
|
>
|
||||||
<UiLogoHaexhub
|
<UiLogoHaexhub class="bg-primary p-3 size-16 rounded-full shrink-0" />
|
||||||
class="bg-primary p-3 size-16 rounded-full shrink-0"
|
|
||||||
/>
|
|
||||||
<span
|
<span
|
||||||
class="flex flex-wrap font-bold text-pretty text-xl gap-2 justify-center"
|
class="flex flex-wrap font-bold text-pretty text-xl gap-2 justify-center"
|
||||||
>
|
>
|
||||||
@ -27,9 +14,7 @@
|
|||||||
<UiTextGradient>Haex Hub</UiTextGradient>
|
<UiTextGradient>Haex Hub</UiTextGradient>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div
|
<div class="flex flex-col gap-4 h-24 items-stretch justify-center">
|
||||||
class="flex flex-col md:flex-row gap-4 w-full h-24 md:h-auto"
|
|
||||||
>
|
|
||||||
<HaexVaultCreate />
|
<HaexVaultCreate />
|
||||||
|
|
||||||
<HaexVaultOpen
|
<HaexVaultOpen
|
||||||
@ -40,9 +25,9 @@
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
v-show="lastVaults.length"
|
v-show="lastVaults.length"
|
||||||
class="w-full"
|
class="max-w-md w-full sm:px-5"
|
||||||
>
|
>
|
||||||
<div class="font-thin text-sm justify-start px-2 pb-1">
|
<div class="font-thin text-sm pb-1 w-full">
|
||||||
{{ t('lastUsed') }}
|
{{ t('lastUsed') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -54,10 +39,19 @@
|
|||||||
:key="vault.name"
|
:key="vault.name"
|
||||||
class="flex items-center justify-between group overflow-x-scroll"
|
class="flex items-center justify-between group overflow-x-scroll"
|
||||||
>
|
>
|
||||||
<UButton
|
<UiButtonContext
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
color="neutral"
|
color="neutral"
|
||||||
class="flex items-center no-underline justify-between text-nowrap text-sm md:text-base shrink w-full px-3"
|
size="xl"
|
||||||
|
class="flex items-center no-underline justify-between text-nowrap text-sm md:text-base shrink w-full hover:bg-default"
|
||||||
|
:context-menu-items="[
|
||||||
|
{
|
||||||
|
icon: 'mdi:trash-can-outline',
|
||||||
|
label: t('remove.button'),
|
||||||
|
onSelect: () => prepareRemoveVault(vault.name),
|
||||||
|
color: 'error',
|
||||||
|
},
|
||||||
|
]"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
passwordPromptOpen = true
|
passwordPromptOpen = true
|
||||||
@ -68,7 +62,7 @@
|
|||||||
<span class="block">
|
<span class="block">
|
||||||
{{ vault.name }}
|
{{ vault.name }}
|
||||||
</span>
|
</span>
|
||||||
</UButton>
|
</UiButtonContext>
|
||||||
<UButton
|
<UButton
|
||||||
color="error"
|
color="error"
|
||||||
square
|
square
|
||||||
@ -99,14 +93,9 @@
|
|||||||
<UiDialogConfirm
|
<UiDialogConfirm
|
||||||
v-model:open="showRemoveDialog"
|
v-model:open="showRemoveDialog"
|
||||||
:title="t('remove.title')"
|
:title="t('remove.title')"
|
||||||
:description="
|
:description="t('remove.description', { vaultName: vaultToBeRemoved })"
|
||||||
t('remove.description', { vaultName: vaultToBeRemoved })
|
|
||||||
"
|
|
||||||
@confirm="onConfirmRemoveAsync"
|
@confirm="onConfirmRemoveAsync"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</UDashboardPanel>
|
|
||||||
</NuxtLayout>
|
</NuxtLayout>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -129,6 +118,9 @@ const showRemoveDialog = ref(false)
|
|||||||
|
|
||||||
const { lastVaults } = storeToRefs(useLastVaultStore())
|
const { lastVaults } = storeToRefs(useLastVaultStore())
|
||||||
|
|
||||||
|
const { syncLastVaultsAsync, moveVaultToTrashAsync } = useLastVaultStore()
|
||||||
|
const { syncDeviceIdAsync } = useDeviceStore()
|
||||||
|
|
||||||
const vaultToBeRemoved = ref('')
|
const vaultToBeRemoved = ref('')
|
||||||
const prepareRemoveVault = (vaultName: string) => {
|
const prepareRemoveVault = (vaultName: string) => {
|
||||||
vaultToBeRemoved.value = vaultName
|
vaultToBeRemoved.value = vaultName
|
||||||
@ -138,7 +130,7 @@ const prepareRemoveVault = (vaultName: string) => {
|
|||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
const onConfirmRemoveAsync = async () => {
|
const onConfirmRemoveAsync = async () => {
|
||||||
try {
|
try {
|
||||||
await removeVaultAsync(vaultToBeRemoved.value)
|
await moveVaultToTrashAsync(vaultToBeRemoved.value)
|
||||||
showRemoveDialog.value = false
|
showRemoveDialog.value = false
|
||||||
await syncLastVaultsAsync()
|
await syncLastVaultsAsync()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -149,9 +141,6 @@ const onConfirmRemoveAsync = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { syncLastVaultsAsync, removeVaultAsync } = useLastVaultStore()
|
|
||||||
const { syncDeviceIdAsync } = useDeviceStore()
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
await syncLastVaultsAsync()
|
await syncLastVaultsAsync()
|
||||||
@ -168,6 +157,7 @@ de:
|
|||||||
lastUsed: 'Zuletzt verwendete Vaults'
|
lastUsed: 'Zuletzt verwendete Vaults'
|
||||||
sponsors: Supported by
|
sponsors: Supported by
|
||||||
remove:
|
remove:
|
||||||
|
button: Löschen
|
||||||
title: Vault löschen
|
title: Vault löschen
|
||||||
description: Möchtest du die Vault {vaultName} wirklich löschen?
|
description: Möchtest du die Vault {vaultName} wirklich löschen?
|
||||||
|
|
||||||
@ -176,6 +166,7 @@ en:
|
|||||||
lastUsed: 'Last used Vaults'
|
lastUsed: 'Last used Vaults'
|
||||||
sponsors: 'Supported by'
|
sponsors: 'Supported by'
|
||||||
remove:
|
remove:
|
||||||
|
button: Delete
|
||||||
title: Delete Vault
|
title: Delete Vault
|
||||||
description: Are you sure you really want to delete {vaultName}?
|
description: Are you sure you really want to delete {vaultName}?
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
v-model:open="showNewDeviceDialog"
|
v-model:open="showNewDeviceDialog"
|
||||||
:confirm-label="t('newDevice.save')"
|
:confirm-label="t('newDevice.save')"
|
||||||
:title="t('newDevice.title')"
|
:title="t('newDevice.title')"
|
||||||
|
:description="t('newDevice.setName')"
|
||||||
confirm-icon="mdi:content-save-outline"
|
confirm-icon="mdi:content-save-outline"
|
||||||
@abort="showNewDeviceDialog = false"
|
@abort="showNewDeviceDialog = false"
|
||||||
@confirm="onSetDeviceNameAsync"
|
@confirm="onSetDeviceNameAsync"
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<div>
|
||||||
<UDashboardPanel resizable>
|
<UDashboardPanel resizable>
|
||||||
<HaexDesktop />
|
<HaexDesktop />
|
||||||
</UDashboardPanel>
|
</UDashboardPanel>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|||||||
@ -10,7 +10,9 @@ export const useUiStore = defineStore('uiStore', () => {
|
|||||||
const isSmallScreen = breakpoints.smaller('sm')
|
const isSmallScreen = breakpoints.smaller('sm')
|
||||||
|
|
||||||
const { $i18n } = useNuxtApp()
|
const { $i18n } = useNuxtApp()
|
||||||
const { locale } = useI18n()
|
const { locale } = useI18n({
|
||||||
|
useScope: 'global',
|
||||||
|
})
|
||||||
const { platform } = useDeviceStore()
|
const { platform } = useDeviceStore()
|
||||||
|
|
||||||
$i18n.setLocaleMessage('de', {
|
$i18n.setLocaleMessage('de', {
|
||||||
|
|||||||
@ -22,9 +22,14 @@ export const useLastVaultStore = defineStore('lastVaultStore', () => {
|
|||||||
return await invoke('delete_vault', { vaultName })
|
return await invoke('delete_vault', { vaultName })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const moveVaultToTrashAsync = async (vaultName: string) => {
|
||||||
|
return await invoke('move_vault_to_trash', { vaultName })
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
syncLastVaultsAsync,
|
syncLastVaultsAsync,
|
||||||
lastVaults,
|
lastVaults,
|
||||||
removeVaultAsync,
|
removeVaultAsync,
|
||||||
|
moveVaultToTrashAsync,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user