Compare commits
153 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| af6615ca98 | |||
| bfd176e338 | |||
| 0800cf2327 | |||
| 32dd6561ab | |||
| 690be31a1d | |||
| 5cb6b44744 | |||
| 0c315e9250 | |||
| ff4a04265b | |||
| 040c8afef2 | |||
| de00d087f6 | |||
| afffe6958b | |||
| 09e489a79b | |||
| 3c7ea720f7 | |||
| a52ee06d73 | |||
| 744e608b1d | |||
| c1e46ddedf | |||
| ca612b33bb | |||
| 8ada70dcf7 | |||
| d21553088e | |||
| f37ef1df8f | |||
| df9cc34c5d | |||
| d176ae396c | |||
| 66190fc7af | |||
| c92b1f1e8b | |||
| d0700d0475 | |||
| 095783baa9 | |||
| de38fceff2 | |||
| 5cc84991f2 | |||
| 150a1921f9 | |||
| a7aad94755 | |||
| ff3d4b4a18 | |||
| f70f749216 | |||
| fd565e1edc | |||
| 83725e1a2a | |||
| a543c98ae1 | |||
| a386226073 | |||
| 6f9db2187f | |||
| 1662fbab2b | |||
| 0eb0b223a2 | |||
| 524fa61c01 | |||
| 0306842284 | |||
| 2d20634107 | |||
| eaacfb2189 | |||
| 75292b0011 | |||
| d73ee5660d | |||
| e5757026fb | |||
| 02021b4446 | |||
| 16173ede84 | |||
| f6723f9723 | |||
| b8f0d7d498 | |||
| a0707e6113 | |||
| 5da2069eba | |||
| 368953c0d6 | |||
| 3a5269acfc | |||
| 5b891074da | |||
| 478e455e24 | |||
| bac3aa25e7 | |||
| cf41b6880d | |||
| 79839951bb | |||
| 56b64a7885 | |||
| 90aec9edf2 | |||
| 9da1e56bc8 | |||
| 352d9085c3 | |||
| f6a6849a9e | |||
| f8f6564d55 | |||
| 18d53ad054 | |||
| 087e3cf92f | |||
| 9cc58c8772 | |||
| 8335a68b0f | |||
| 40392e117e | |||
| 07d6b18ccf | |||
| 08926e76e4 | |||
| 2de368847c | |||
| d34eaafd34 | |||
| e0375bf9a9 | |||
| a306fdf3bd | |||
| a7e0d7bef9 | |||
| 6028a41d65 | |||
| 768c286d4a | |||
| 44d75881f9 | |||
| 3be18b8e5d | |||
| 858f0e13bd | |||
| 49c7075b92 | |||
| 0bdaa66d24 | |||
| 32286d03de | |||
| 817430f11b | |||
| 1dc045ef1e | |||
| 72a03dac33 | |||
| cee7809155 | |||
| 4ccd2845fb | |||
| b4812e6659 | |||
| f0100c0c0c | |||
| ed718704ee | |||
| dffe5fb05a | |||
| 03d7ae05e0 | |||
| 2f55bb3f6d | |||
| c151c2936c | |||
| 7c77c8e850 | |||
| 667ad72583 | |||
| 4b71e80636 | |||
| 07327845b3 | |||
| d043f9c416 | |||
| eadd3bfc48 | |||
| 26bd0722bc | |||
| 443c85c9b5 | |||
| efcc11771e | |||
| 4288eb2c02 | |||
| e009af0575 | |||
| c466d93519 | |||
| d4968b935b | |||
| f45817d4ac | |||
| a6aae9d6f2 | |||
| 838c69f46e | |||
| 0b7ace5dfa | |||
| 8f0f8db201 | |||
| ceda17edc4 | |||
| 12c860de0c | |||
| 12a559dc6d | |||
| 938fa0953b | |||
| 5f678ff088 | |||
| df39489916 | |||
| b2288bc9b2 | |||
| 0923312111 | |||
| 279117ecf2 | |||
| adb017804d | |||
| 0e700b335a | |||
| a7b93deb98 | |||
| 99fb77b867 | |||
| 6f543f8bef | |||
| 473028491c | |||
| a598ba6049 | |||
| a7ced9d477 | |||
| 646da8276a | |||
| af9ad2eb6f | |||
| 9d12943e3a | |||
| b670ef0e32 | |||
| a823e45535 | |||
| 36887eaf40 | |||
| 9809657b84 | |||
| 2b61520524 | |||
| 8b7bced138 | |||
| 24d34c77d5 | |||
| e72e44bb12 | |||
| 08fcd330e1 | |||
| 0a5f14508c | |||
| a2077499a0 | |||
| 18b8f696a1 | |||
| 957f2a9f77 | |||
| 89804c83ac | |||
| a396a54f90 | |||
| 3930144876 | |||
| d2b51ee0e6 | |||
| 086ba8b77a |
@@ -0,0 +1 @@
|
||||
81e1a25de641f0292863b1404cba728c1eadd00d
|
||||
@@ -0,0 +1,301 @@
|
||||
name: Build Lotus Chat Desktop
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
GITEA_URL: https://code.lotusguild.org
|
||||
REPO: LotusGuild/cinny-desktop
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.ver.outputs.version }}
|
||||
release_id: ${{ steps.release.outputs.release_id }}
|
||||
steps:
|
||||
- name: Compute version
|
||||
id: ver
|
||||
run: echo "version=4.12.${{ github.run_number }}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create or update release
|
||||
id: release
|
||||
env:
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
run: |
|
||||
VERSION="4.12.${{ github.run_number }}"
|
||||
EXISTING=$(curl -sf "$GITEA_URL/api/v1/repos/$REPO/releases/tags/latest" \
|
||||
-H "Authorization: token $TOKEN" 2>/dev/null || true)
|
||||
RELEASE_ID=$(echo "$EXISTING" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('id',''))" 2>/dev/null || true)
|
||||
if [ -n "$RELEASE_ID" ] && [ "$RELEASE_ID" != "None" ] && [ "$RELEASE_ID" != "" ]; then
|
||||
curl -sf -X PATCH "$GITEA_URL/api/v1/repos/$REPO/releases/$RELEASE_ID" \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"name\":\"Lotus Chat $VERSION\",\"body\":\"Built from ${{ github.sha }}\"}" > /dev/null
|
||||
else
|
||||
RELEASE_ID=$(curl -sf -X POST "$GITEA_URL/api/v1/repos/$REPO/releases" \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"tag_name\":\"latest\",\"name\":\"Lotus Chat $VERSION\",\"prerelease\":true,\"body\":\"Built from ${{ github.sha }}\"}" \
|
||||
| python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
|
||||
fi
|
||||
echo "release_id=$RELEASE_ID" >> $GITHUB_OUTPUT
|
||||
|
||||
build-windows:
|
||||
needs: prepare
|
||||
runs-on: windows
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
|
||||
- name: Checkout submodules (shallow)
|
||||
shell: powershell
|
||||
run: git submodule update --init --depth=1
|
||||
|
||||
- name: Patch version
|
||||
shell: powershell
|
||||
run: |
|
||||
$ver = '${{ needs.prepare.outputs.version }}'
|
||||
node -e "const fs=require('fs');const d=JSON.parse(fs.readFileSync('src-tauri/tauri.conf.json','utf8'));d.version='$ver';fs.writeFileSync('src-tauri/tauri.conf.json',JSON.stringify(d,null,2),'utf8');"
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: src-tauri
|
||||
|
||||
- name: Install frontend deps
|
||||
shell: powershell
|
||||
run: cd cinny; npm ci
|
||||
|
||||
- name: Install Tauri deps
|
||||
shell: powershell
|
||||
run: npm ci
|
||||
|
||||
- name: Build
|
||||
shell: powershell
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ''
|
||||
NODE_OPTIONS: '--max_old_space_size=4096'
|
||||
# Sparse registry avoids a full git clone of the crates.io index —
|
||||
# eliminates the curl SSL handshake failures seen on Windows runners.
|
||||
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
|
||||
# Disable HTTP/2 multiplexing — ALPN negotiation can reset on Windows Schannel.
|
||||
CARGO_HTTP_MULTIPLEXING: 'false'
|
||||
# Retry transient network errors before failing.
|
||||
CARGO_NET_RETRY: '5'
|
||||
run: |
|
||||
# USERPROFILE is set by Windows directly; more reliable than C:\Users\$USERNAME
|
||||
$env:PATH = "$env:USERPROFILE\.cargo\bin;$env:PATH"
|
||||
# Also add the actual toolchain bin to bypass rustup shim execution issues
|
||||
$toolchain = Get-ChildItem "$env:USERPROFILE\.rustup\toolchains" -Directory -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.Name -match 'stable' } | Select-Object -First 1
|
||||
if ($toolchain) { $env:PATH = "$($toolchain.FullName)\bin;$env:PATH" }
|
||||
Write-Host "cargo: $((Get-Command cargo -ErrorAction SilentlyContinue).Source)"
|
||||
cargo --version
|
||||
npm run tauri -- build --bundles nsis
|
||||
|
||||
- name: Upload to release
|
||||
shell: powershell
|
||||
env:
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
RELEASE_ID: ${{ needs.prepare.outputs.release_id }}
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
run: |
|
||||
$releaseId = $env:RELEASE_ID
|
||||
$VERSION = $env:VERSION
|
||||
Write-Host "Version: $VERSION Release: $releaseId"
|
||||
|
||||
$nsis = "src-tauri\target\release\bundle\nsis"
|
||||
$files = @(
|
||||
"$nsis\Lotus Chat_${VERSION}_x64-setup.exe",
|
||||
"$nsis\Lotus Chat_${VERSION}_x64-setup.nsis.zip",
|
||||
"$nsis\Lotus Chat_${VERSION}_x64-setup.nsis.zip.sig"
|
||||
)
|
||||
$names = @("LotusChat-x86_64-setup.exe", "LotusChat-x86_64-setup.nsis.zip", "LotusChat-x86_64-setup.nsis.zip.sig")
|
||||
for ($i = 0; $i -lt $files.Length; $i++) {
|
||||
$existing = (Invoke-RestMethod -Uri "$env:GITEA_URL/api/v1/repos/$env:REPO/releases/$releaseId/assets" `
|
||||
-Headers @{ Authorization = "token $env:TOKEN" }) | Where-Object { $_.name -eq $names[$i] }
|
||||
if ($existing) {
|
||||
Invoke-RestMethod -Uri "$env:GITEA_URL/api/v1/repos/$env:REPO/releases/$releaseId/assets/$($existing.id)" `
|
||||
-Method Delete -Headers @{ Authorization = "token $env:TOKEN" }
|
||||
}
|
||||
$bytes = [System.IO.File]::ReadAllBytes($files[$i])
|
||||
Invoke-RestMethod -Uri "$env:GITEA_URL/api/v1/repos/$env:REPO/releases/$releaseId/assets?name=$($names[$i])" `
|
||||
-Method Post `
|
||||
-Headers @{ Authorization = "token $env:TOKEN"; "Content-Type" = "application/octet-stream" } `
|
||||
-Body $bytes
|
||||
}
|
||||
|
||||
build-linux:
|
||||
needs: prepare
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
|
||||
- name: Install system deps
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y \
|
||||
curl wget file gcc imagemagick \
|
||||
libwebkit2gtk-4.1-dev \
|
||||
libssl-dev \
|
||||
libxdo-dev \
|
||||
libayatana-appindicator3-dev \
|
||||
librsvg2-dev \
|
||||
patchelf \
|
||||
xdg-utils \
|
||||
squashfs-tools
|
||||
|
||||
- name: Ensure icons are RGBA PNG
|
||||
run: |
|
||||
for f in src-tauri/icons/*.png; do
|
||||
info=$(identify -verbose "$f" 2>/dev/null | grep "Type:" | head -1)
|
||||
echo "$f: $info"
|
||||
convert "$f" -type TrueColorAlpha PNG32:"$f"
|
||||
done
|
||||
|
||||
- name: Set up Rust toolchain
|
||||
run: |
|
||||
source "$HOME/.cargo/env" 2>/dev/null || true
|
||||
if command -v cargo >/dev/null 2>&1; then
|
||||
echo "Using existing Rust: $(cargo --version)"
|
||||
else
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path --default-toolchain stable --profile minimal
|
||||
source "$HOME/.cargo/env"
|
||||
fi
|
||||
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: src-tauri
|
||||
|
||||
- name: Patch version
|
||||
run: python3 -c "import json; d=json.load(open('src-tauri/tauri.conf.json')); d['version']='${{ needs.prepare.outputs.version }}'; open('src-tauri/tauri.conf.json','w').write(json.dumps(d,indent=2))"
|
||||
|
||||
- name: Install frontend deps
|
||||
run: cd cinny && npm ci
|
||||
|
||||
- name: Install Tauri deps
|
||||
run: npm ci
|
||||
|
||||
- name: Stage AppRun and linuxdeploy for AppImage bundler
|
||||
run: |
|
||||
set -e
|
||||
mkdir -p ~/.cache/tauri
|
||||
cp tools/AppRun-x86_64 ~/.cache/tauri/AppRun-x86_64
|
||||
chmod +x ~/.cache/tauri/AppRun-x86_64
|
||||
|
||||
wget -q \
|
||||
"https://github.com/tauri-apps/binary-releases/releases/download/linuxdeploy/linuxdeploy-x86_64.AppImage" \
|
||||
-O /tmp/linuxdeploy.AppImage
|
||||
chmod +x /tmp/linuxdeploy.AppImage
|
||||
|
||||
rm -rf /root/linuxdeploy-root
|
||||
(cd /root && /tmp/linuxdeploy.AppImage --appimage-extract)
|
||||
mv /root/squashfs-root /root/linuxdeploy-root
|
||||
echo "Extracted linuxdeploy:"
|
||||
ls /root/linuxdeploy-root/
|
||||
ls /root/linuxdeploy-root/usr/bin/ 2>/dev/null || echo "no usr/bin"
|
||||
|
||||
# Pre-stage plugin scripts next to linuxdeploy so it finds them via /proc/self/exe lookup
|
||||
wget -q "https://raw.githubusercontent.com/tauri-apps/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh" \
|
||||
-O /root/linuxdeploy-root/usr/bin/linuxdeploy-plugin-gtk.sh
|
||||
wget -q "https://raw.githubusercontent.com/tauri-apps/linuxdeploy-plugin-gstreamer/master/linuxdeploy-plugin-gstreamer.sh" \
|
||||
-O /root/linuxdeploy-root/usr/bin/linuxdeploy-plugin-gstreamer.sh
|
||||
chmod +x /root/linuxdeploy-root/usr/bin/linuxdeploy-plugin-gtk.sh \
|
||||
/root/linuxdeploy-root/usr/bin/linuxdeploy-plugin-gstreamer.sh
|
||||
|
||||
gcc -o ~/.cache/tauri/linuxdeploy-x86_64.AppImage tools/ld_wrapper.c
|
||||
chmod +x ~/.cache/tauri/linuxdeploy-x86_64.AppImage
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ''
|
||||
NODE_OPTIONS: '--max_old_space_size=4096'
|
||||
RUST_LOG: tauri_bundler=debug
|
||||
run: npm run tauri -- build --bundles appimage,deb
|
||||
|
||||
- name: Show linuxdeploy wrapper log
|
||||
if: always()
|
||||
run: cat /tmp/ld-wrapper.log 2>/dev/null || echo "no wrapper log found"
|
||||
|
||||
- name: Upload to release
|
||||
env:
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
RELEASE_ID: ${{ needs.prepare.outputs.release_id }}
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
run: |
|
||||
APPIMAGE_DIR="src-tauri/target/release/bundle/appimage"
|
||||
DEB_DIR="src-tauri/target/release/bundle/deb"
|
||||
|
||||
upload() {
|
||||
local name="$1" path="$2"
|
||||
local existing_id
|
||||
existing_id=$(curl -sf "$GITEA_URL/api/v1/repos/$REPO/releases/$RELEASE_ID/assets" \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
| python3 -c "import sys,json; assets=json.load(sys.stdin); print(next((str(a['id']) for a in assets if a['name']=='$name'), ''))" 2>/dev/null || true)
|
||||
if [ -n "$existing_id" ]; then
|
||||
curl -sf -X DELETE "$GITEA_URL/api/v1/repos/$REPO/releases/$RELEASE_ID/assets/$existing_id" \
|
||||
-H "Authorization: token $TOKEN" || true
|
||||
fi
|
||||
echo "Uploading $name"
|
||||
curl -sf -X POST \
|
||||
"$GITEA_URL/api/v1/repos/$REPO/releases/$RELEASE_ID/assets?name=$name" \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary @"$path"
|
||||
}
|
||||
|
||||
upload "LotusChat-x86_64.AppImage" "$APPIMAGE_DIR/Lotus Chat_${VERSION}_amd64.AppImage"
|
||||
upload "LotusChat-x86_64.AppImage.tar.gz" "$APPIMAGE_DIR/Lotus Chat_${VERSION}_amd64.AppImage.tar.gz"
|
||||
upload "LotusChat-x86_64.AppImage.tar.gz.sig" "$APPIMAGE_DIR/Lotus Chat_${VERSION}_amd64.AppImage.tar.gz.sig"
|
||||
upload "LotusChat-x86_64.deb" "$DEB_DIR/Lotus Chat_${VERSION}_amd64.deb"
|
||||
|
||||
update-manifest:
|
||||
needs: [prepare, build-windows, build-linux]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Generate and upload release.json
|
||||
env:
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
RELEASE_ID: ${{ needs.prepare.outputs.release_id }}
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
run: |
|
||||
BASE="$GITEA_URL/LotusGuild/cinny-desktop/releases/download/latest"
|
||||
|
||||
WIN_SIG=$(curl -sf "$BASE/LotusChat-x86_64-setup.nsis.zip.sig")
|
||||
LIN_SIG=$(curl -sf "$BASE/LotusChat-x86_64.AppImage.tar.gz.sig")
|
||||
DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
|
||||
python3 -c "import json,sys; v,d,wu,ws,lu,ls=sys.argv[1:]; print(json.dumps({'version':v,'notes':'Latest Lotus Chat release','pub_date':d,'platforms':{'windows-x86_64':{'url':wu,'signature':ws},'linux-x86_64':{'url':lu,'signature':ls}}},indent=2))" \
|
||||
"$VERSION" "$DATE" \
|
||||
"$BASE/LotusChat-x86_64-setup.nsis.zip" "$WIN_SIG" \
|
||||
"$BASE/LotusChat-x86_64.AppImage.tar.gz" "$LIN_SIG" \
|
||||
> release.json
|
||||
|
||||
cat release.json
|
||||
|
||||
OLD=$(curl -sf "$GITEA_URL/api/v1/repos/$REPO/releases/$RELEASE_ID/assets" \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
| python3 -c "import sys,json; print(next((str(a['id']) for a in json.load(sys.stdin) if a['name']=='release.json'), ''))" 2>/dev/null || true)
|
||||
[ -n "$OLD" ] && curl -sf -X DELETE \
|
||||
"$GITEA_URL/api/v1/repos/$REPO/releases/$RELEASE_ID/assets/$OLD" \
|
||||
-H "Authorization: token $TOKEN" || true
|
||||
|
||||
curl -sf -X POST \
|
||||
"$GITEA_URL/api/v1/repos/$REPO/releases/$RELEASE_ID/assets?name=release.json" \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data-binary @release.json
|
||||
@@ -1,58 +0,0 @@
|
||||
name: 🐞 Bug Report
|
||||
description: Report a bug
|
||||
labels: 'type: bug'
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## First of all
|
||||
1. Please search for [existing issues](https://github.com/cinnyapp/cinny-desktop/issues?q=is%3Aissue) about this problem first.
|
||||
2. Make sure Cinny is up to date.
|
||||
3. Make sure it's an issue with Cinny and not something else you are using.
|
||||
4. Remember to be friendly.
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: A clear description of what the bug is. Include screenshots if applicable.
|
||||
placeholder: Bug description
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Reproduction
|
||||
description: Steps to reproduce the behavior.
|
||||
placeholder: |
|
||||
1. Go to ...
|
||||
2. Click on ...
|
||||
3. See error
|
||||
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: A clear description of what you expected to happen.
|
||||
|
||||
- type: textarea
|
||||
id: info
|
||||
attributes:
|
||||
label: Platform and versions
|
||||
description: "Provide OS, browser and Cinny version with your Homeserver."
|
||||
placeholder: |
|
||||
1. OS: [e.g. Windows 10, MacOS]
|
||||
2. Cinny version: [e.g. 1.8.1]
|
||||
3. Matrix homeserver: [e.g. matrix.org]
|
||||
4. Downloaded from: [e.g. GitHub, Flatpak]
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context about the problem here.
|
||||
@@ -1,4 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💬 Matrix Chat
|
||||
url: https://matrix.to/#/#cinny:matrix.org
|
||||
about: Ask questions and talk to other Cinny users and the maintainers
|
||||
- name: Features, Bug Reports, Questions
|
||||
url: https://github.com/cinnyapp/cinny/discussions/new/choose
|
||||
about: Our preferred starting point if you have any questions or suggestions about features or behavior.
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
name: 💡 Feature Request
|
||||
description: Suggest an idea
|
||||
labels: 'type: feature'
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Describe the problem
|
||||
description: A clear description of the problem this feature would solve
|
||||
placeholder: "I'm always frustrated when..."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: "Describe the solution you'd like"
|
||||
description: A clear description of what change you would like
|
||||
placeholder: "I would like to..."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives considered
|
||||
description: "Any alternative solutions you've considered"
|
||||
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context about the problem here.
|
||||
@@ -1,22 +0,0 @@
|
||||
<!-- Please read https://github.com/cinnyapp/cinny/blob/dev/CONTRIBUTING.md before submitting your pull request -->
|
||||
|
||||
### Description
|
||||
<!-- Please include a summary of the change. Please also include relevant motivation and context. List any dependencies that are required for this change. -->
|
||||
|
||||
|
||||
Fixes #
|
||||
|
||||
#### Type of change
|
||||
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] This change requires a documentation update
|
||||
|
||||
### Checklist:
|
||||
|
||||
- [ ] My code follows the style guidelines of this project
|
||||
- [ ] I have performed a self-review of my own code
|
||||
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||
- [ ] I have made corresponding changes to the documentation
|
||||
- [ ] My changes generate no new warnings
|
||||
@@ -1,3 +0,0 @@
|
||||
# Reporting a Vulnerability
|
||||
|
||||
**If you've found a security vulnerability, please report it to cinnyapp@gmail.com**
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
cd ..
|
||||
zip ${{ github.event.repository.name }}/${{ github.event.repository.name }}-${{ github.ref_name }}.zip ${{ github.event.repository.name }} -r
|
||||
- name: Upload zip to release
|
||||
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3
|
||||
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
|
||||
with:
|
||||
files: |
|
||||
${{ github.event.repository.name }}-${{ github.ref_name }}.zip
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
with:
|
||||
node-version-file: ".node-version"
|
||||
package-manager-cache: false
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
- name: Get app version (windows)
|
||||
run: |
|
||||
$json = (Get-Content "src-tauri\tauri.conf.json" -Raw) | ConvertFrom-Json
|
||||
$version = $json.package.version
|
||||
$version = $json.version
|
||||
echo "Version: ${version}"
|
||||
echo "TAURI_VERSION=${version}" >> $Env:GITHUB_ENV
|
||||
echo "${Env:TAURI_VERSION}"
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
run: Move-Item "src-tauri\target\release\bundle\msi\Cinny_${{ env.TAURI_VERSION }}_x64_en-US.msi.zip.sig" "src-tauri\target\release\bundle\msi\Cinny_desktop-x86_64.msi.zip.sig"
|
||||
shell: pwsh
|
||||
- name: Upload tagged release
|
||||
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3
|
||||
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
|
||||
with:
|
||||
files: |
|
||||
src-tauri/target/release/bundle/msi/Cinny_desktop-x86_64.msi
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
with:
|
||||
node-version-file: ".node-version"
|
||||
package-manager-cache: false
|
||||
@@ -87,7 +87,7 @@ jobs:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
- name: Get app version
|
||||
id: vars
|
||||
run: echo "tag=$(jq .package.version src-tauri/tauri.conf.json | tr -d '"')" >> $GITHUB_OUTPUT
|
||||
run: echo "tag=$(jq .version src-tauri/tauri.conf.json | tr -d '"')" >> $GITHUB_OUTPUT
|
||||
- name: Move deb
|
||||
run: mv "src-tauri/target/release/bundle/deb/Cinny_${{ steps.vars.outputs.tag }}_amd64.deb" "src-tauri/target/release/bundle/deb/Cinny_desktop-x86_64.deb"
|
||||
- name: Move AppImage
|
||||
@@ -97,7 +97,7 @@ jobs:
|
||||
- name: Move AppImage.tar.gz.sig
|
||||
run: mv "src-tauri/target/release/bundle/appimage/Cinny_${{ steps.vars.outputs.tag }}_amd64.AppImage.tar.gz.sig" "src-tauri/target/release/bundle/appimage/Cinny_desktop-x86_64.AppImage.tar.gz.sig"
|
||||
- name: Upload tagged release
|
||||
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3
|
||||
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
|
||||
with:
|
||||
files: |
|
||||
src-tauri/target/release/bundle/deb/Cinny_desktop-x86_64.deb
|
||||
@@ -114,7 +114,7 @@ jobs:
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
with:
|
||||
node-version-file: ".node-version"
|
||||
package-manager-cache: false
|
||||
@@ -137,7 +137,7 @@ jobs:
|
||||
args: "--target universal-apple-darwin"
|
||||
- name: Get app version
|
||||
id: vars
|
||||
run: echo "tag=$(jq .package.version src-tauri/tauri.conf.json | tr -d '"')" >> $GITHUB_OUTPUT
|
||||
run: echo "tag=$(jq .version src-tauri/tauri.conf.json | tr -d '"')" >> $GITHUB_OUTPUT
|
||||
- name: Move dmg
|
||||
run: mv "src-tauri/target/universal-apple-darwin/release/bundle/dmg/Cinny_${{ steps.vars.outputs.tag }}_universal.dmg" "src-tauri/target/universal-apple-darwin/release/bundle/dmg/Cinny_desktop-universal.dmg"
|
||||
- name: Move app.tar.gz
|
||||
@@ -145,7 +145,7 @@ jobs:
|
||||
- name: Move app.tar.gz.sig
|
||||
run: mv "src-tauri/target/universal-apple-darwin/release/bundle/macos/Cinny.app.tar.gz.sig" "src-tauri/target/universal-apple-darwin/release/bundle/macos/Cinny_desktop-universal.app.tar.gz.sig"
|
||||
- name: Upload tagged release
|
||||
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3
|
||||
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
|
||||
with:
|
||||
files: |
|
||||
src-tauri/target/universal-apple-darwin/release/bundle/dmg/Cinny_desktop-universal.dmg
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
with:
|
||||
node-version-file: ".node-version"
|
||||
package-manager-cache: false
|
||||
@@ -44,8 +44,35 @@ jobs:
|
||||
uses: tauri-apps/tauri-action@73fb865345c54760d875b94642314f8c0c894afa # v0.6.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
with:
|
||||
args: ${{ matrix.args }}
|
||||
args: ${{ matrix.args }} --config '{"bundle":{"createUpdaterArtifacts":false}}'
|
||||
- name: Upload macOS artifacts
|
||||
if: matrix.platform == 'macos-latest'
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: release-artifacts-macos
|
||||
path: |
|
||||
src-tauri/target/universal-apple-darwin/release/bundle/macos/Cinny*.app
|
||||
if-no-files-found: warn
|
||||
|
||||
- name: Upload Linux artifacts
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: release-artifacts-linux
|
||||
path: |
|
||||
src-tauri/target/release/bundle/deb/Cinny_*.deb
|
||||
src-tauri/target/release/bundle/rpm/Cinny-*.rpm
|
||||
src-tauri/target/release/bundle/appimage/Cinny_*.AppImage
|
||||
if-no-files-found: warn
|
||||
|
||||
- name: Upload Windows artifacts
|
||||
if: matrix.platform == 'windows-latest'
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: release-artifacts-windows
|
||||
path: |
|
||||
src-tauri/target/release/bundle/msi/Cinny_*_x64_*.msi
|
||||
src-tauri/target/release/bundle/nsis/Cinny_*_x64-setup.exe
|
||||
if-no-files-found: warn
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
[submodule "cinny"]
|
||||
path = cinny
|
||||
url = https://github.com/cinnyapp/cinny.git
|
||||
url = https://code.lotusguild.org/LotusGuild/cinny.git
|
||||
branch = lotus
|
||||
|
||||
@@ -23,7 +23,7 @@ To verify release files, you need to download [minisign](https://jedisct1.github
|
||||
|
||||
## Local development
|
||||
|
||||
Firstly, to setup Rust, NodeJS and build tools follow [Tauri documentation](https://tauri.app/v1/guides/getting-started/prerequisites).
|
||||
Firstly, to setup Rust, NodeJS and build tools follow [Tauri documentation](https://v2.tauri.app/start/prerequisites/).
|
||||
|
||||
Now, to setup development locally run the following commands:
|
||||
* `git clone --recursive https://github.com/cinnyapp/cinny-desktop.git`
|
||||
|
||||
@@ -1,37 +1,13 @@
|
||||
{
|
||||
"defaultHomeserver": 1,
|
||||
"defaultHomeserver": 0,
|
||||
"homeserverList": [
|
||||
"converser.eu",
|
||||
"matrix.lotusguild.org",
|
||||
"matrix.org",
|
||||
"mozilla.org",
|
||||
"unredacted.org",
|
||||
"xmr.se"
|
||||
"mozilla.org"
|
||||
],
|
||||
"allowCustomHomeservers": true,
|
||||
|
||||
"featuredCommunities": {
|
||||
"openAsDefault": false,
|
||||
"spaces": [
|
||||
"#cinny-space:matrix.org",
|
||||
"#community:matrix.org",
|
||||
"#space:unredacted.org",
|
||||
"#science-space:matrix.org",
|
||||
"#libregaming-games:tchncs.de",
|
||||
"#mathematics-on:matrix.org"
|
||||
],
|
||||
"rooms": [
|
||||
"#cinny:matrix.org",
|
||||
"#freesoftware:matrix.org",
|
||||
"#pcapdroid:matrix.org",
|
||||
"#gentoo:matrix.org",
|
||||
"#PrivSec.dev:arcticfoxes.net",
|
||||
"#disroot:aria-net.org"
|
||||
],
|
||||
"servers": [ "matrix.org", "mozilla.org", "unredacted.org" ]
|
||||
},
|
||||
|
||||
"hashRouter": {
|
||||
"enabled": true,
|
||||
"basename": "/"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "cinny",
|
||||
"version": "4.11.1",
|
||||
"version": "4.12.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "cinny",
|
||||
"version": "4.11.1",
|
||||
"version": "4.12.2",
|
||||
"license": "AGPL-3.0-only",
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "2.7.0",
|
||||
@@ -24,7 +24,8 @@
|
||||
"devDependencies": {
|
||||
"@actions/github": "6.0.0",
|
||||
"@tauri-apps/cli": "2.7.1",
|
||||
"node-fetch": "3.3.2"
|
||||
"node-fetch": "3.3.2",
|
||||
"shx": "0.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
@@ -61,6 +62,44 @@
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@nodelib/fs.stat": "2.0.5",
|
||||
"run-parallel": "^1.1.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.stat": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
|
||||
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.walk": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
|
||||
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@nodelib/fs.scandir": "2.1.5",
|
||||
"fastq": "^1.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-token": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
|
||||
@@ -491,6 +530,36 @@
|
||||
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fill-range": "^7.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "6.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz",
|
||||
"integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nice-try": "^1.0.4",
|
||||
"path-key": "^2.0.1",
|
||||
"semver": "^5.5.0",
|
||||
"shebang-command": "^1.2.0",
|
||||
"which": "^1.2.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.8"
|
||||
}
|
||||
},
|
||||
"node_modules/data-uri-to-buffer": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz",
|
||||
@@ -506,6 +575,72 @@
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/end-of-stream": {
|
||||
"version": "1.4.5",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
||||
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/es-errors": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/execa": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
|
||||
"integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^6.0.0",
|
||||
"get-stream": "^4.0.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"npm-run-path": "^2.0.0",
|
||||
"p-finally": "^1.0.0",
|
||||
"signal-exit": "^3.0.0",
|
||||
"strip-eof": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
||||
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
"@nodelib/fs.walk": "^1.2.3",
|
||||
"glob-parent": "^5.1.2",
|
||||
"merge2": "^1.3.0",
|
||||
"micromatch": "^4.0.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fastq": {
|
||||
"version": "1.20.1",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
|
||||
"integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"reusify": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/fetch-blob": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||
@@ -529,6 +664,19 @@
|
||||
"node": "^12.20 || >= 14.13"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/formdata-polyfill": {
|
||||
"version": "4.0.10",
|
||||
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||
@@ -541,6 +689,114 @@
|
||||
"node": ">=12.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stream": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
||||
"integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"pump": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
|
||||
"integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/interpret": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
|
||||
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.16.2",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
|
||||
"integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"hasown": "^2.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
@@ -550,6 +806,64 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-stream": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||
"integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/merge2": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/micromatch": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"braces": "^3.0.3",
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/nice-try": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
||||
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-domexception": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||
@@ -587,6 +901,19 @@
|
||||
"url": "https://opencollective.com/node-fetch"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-path": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
|
||||
"integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
@@ -596,6 +923,259 @@
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/p-finally": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||
"integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/path-key": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
|
||||
"integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
|
||||
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/pump": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
|
||||
"integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/queue-microtask": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/rechoir": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
|
||||
"integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"resolve": "^1.1.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.12",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
|
||||
"integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"is-core-module": "^2.16.1",
|
||||
"path-parse": "^1.0.7",
|
||||
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"resolve": "bin/resolve"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/reusify": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
|
||||
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"iojs": ">=1.0.0",
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/run-parallel": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"queue-microtask": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
|
||||
"integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"shebang-regex": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-regex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
|
||||
"integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/shelljs": {
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.9.2.tgz",
|
||||
"integrity": "sha512-S3I64fEiKgTZzKCC46zT/Ib9meqofLrQVbpSswtjFfAVDW+AZ54WTnAM/3/yENoxz/V1Cy6u3kiiEbQ4DNphvw==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"execa": "^1.0.0",
|
||||
"fast-glob": "^3.3.2",
|
||||
"interpret": "^1.0.0",
|
||||
"rechoir": "^0.6.2"
|
||||
},
|
||||
"bin": {
|
||||
"shjs": "bin/shjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/shx": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/shx/-/shx-0.4.0.tgz",
|
||||
"integrity": "sha512-Z0KixSIlGPpijKgcH6oCMCbltPImvaKy0sGH8AkLRXw1KyzpKtaCTizP2xen+hNDqVF4xxgvA0KXSb9o4Q6hnA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.8",
|
||||
"shelljs": "^0.9.2"
|
||||
},
|
||||
"bin": {
|
||||
"shx": "lib/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/strip-eof": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||
"integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-preserve-symlinks-flag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
@@ -632,6 +1212,19 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"which": "bin/which"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
{
|
||||
"name": "cinny",
|
||||
"version": "4.11.1",
|
||||
"version": "4.12.2",
|
||||
"description": "Yet another matrix client",
|
||||
"main": "index.js",
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"tauri": "cp config.json cinny/ && tauri",
|
||||
"release": "node scripts/release.mjs"
|
||||
"tauri": "shx cp config.json cinny/ && tauri",
|
||||
"release": "node scripts/release.mjs",
|
||||
"bump": "node scripts/update-version.mjs"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Ajay Bura",
|
||||
@@ -29,6 +30,7 @@
|
||||
"devDependencies": {
|
||||
"@actions/github": "6.0.0",
|
||||
"@tauri-apps/cli": "2.7.1",
|
||||
"node-fetch": "3.3.2"
|
||||
"node-fetch": "3.3.2",
|
||||
"shx": "0.4.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { execSync } from "child_process";
|
||||
|
||||
const version = process.argv[2];
|
||||
|
||||
if (!version) {
|
||||
console.error("Missing version");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Preparing release ${version}`);
|
||||
|
||||
// 1. Update npm versions
|
||||
execSync(`npm version ${version} --no-git-tag-version`, {
|
||||
stdio: "inherit"
|
||||
});
|
||||
console.log(`Updated package.json and package-lock.json → ${version}`);
|
||||
|
||||
// 2. Update Cargo.toml
|
||||
const cargoToml = "src-tauri/Cargo.toml";
|
||||
let cargoContent = fs.readFileSync(cargoToml, "utf8");
|
||||
|
||||
cargoContent = cargoContent.replace(
|
||||
/^version\s*=\s*".*"/m,
|
||||
`version = "${version}"`
|
||||
);
|
||||
|
||||
fs.writeFileSync(cargoToml, cargoContent);
|
||||
console.log(`Updated ${cargoToml} → ${version}`);
|
||||
|
||||
// 3. Update tauri.conf.json
|
||||
const tauriConfigPath = "src-tauri/tauri.conf.json";
|
||||
const tauriConfig = JSON.parse(fs.readFileSync(tauriConfigPath));
|
||||
|
||||
tauriConfig.version = version;
|
||||
|
||||
fs.writeFileSync(
|
||||
tauriConfigPath,
|
||||
JSON.stringify(tauriConfig, null, 2) + "\n"
|
||||
);
|
||||
console.log(`Updated ${tauriConfigPath} → ${version}`);
|
||||
|
||||
// 4. Update Cinny web submodule to latest tag
|
||||
console.log("Updating cinny web submodule");
|
||||
|
||||
execSync("git submodule update --init --recursive", { stdio: "inherit" });
|
||||
|
||||
execSync("git fetch --tags", { cwd: "cinny", stdio: "inherit" });
|
||||
|
||||
const latestCommit = execSync("git rev-list --tags --max-count=1", {
|
||||
cwd: "cinny",
|
||||
}).toString().trim();
|
||||
|
||||
const latestTag = execSync(`git describe --tags ${latestCommit}`, {
|
||||
cwd: "cinny",
|
||||
}).toString().trim();
|
||||
|
||||
console.log(`Latest cinny tag: ${latestTag}`);
|
||||
|
||||
execSync(`git checkout ${latestTag}`, { cwd: "cinny", stdio: "inherit" });
|
||||
|
||||
execSync("git add cinny", { stdio: "inherit" });
|
||||
|
||||
console.log("Release preparation complete");
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[package]
|
||||
name = "cinny"
|
||||
version = "4.11.1"
|
||||
version = "4.12.2"
|
||||
description = "Yet another matrix client"
|
||||
authors = ["Ajay Bura"]
|
||||
license = "AGPL-3.0-only"
|
||||
@@ -17,7 +17,7 @@ tauri-build = { version = "2", features = [] }
|
||||
[dependencies]
|
||||
serde_json = "1.0.109"
|
||||
serde = { version = "1.0.193", features = ["derive"] }
|
||||
tauri = { version = "2", features = [ "devtools"] }
|
||||
tauri = { version = "2", features = ["devtools", "wry", "tray-icon", "image-png"] }
|
||||
tauri-plugin-localhost = "2"
|
||||
tauri-plugin-window-state = "2"
|
||||
tauri-plugin-clipboard-manager = "2"
|
||||
@@ -28,6 +28,8 @@ tauri-plugin-http = "2"
|
||||
tauri-plugin-process = "2"
|
||||
tauri-plugin-os = "2"
|
||||
tauri-plugin-dialog = "2"
|
||||
tauri-plugin-opener = "2"
|
||||
tauri-plugin-deep-link = "2"
|
||||
|
||||
[features]
|
||||
# by default Tauri runs in production mode
|
||||
@@ -40,6 +42,17 @@ custom-protocol = [ "tauri/custom-protocol" ]
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
tauri-plugin-global-shortcut = "2"
|
||||
tauri-plugin-updater = "2"
|
||||
tauri-plugin-single-instance = "2"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
webview2-com = "0.38"
|
||||
window-vibrancy = "0.6"
|
||||
windows = { version = "0.61", features = [
|
||||
"Win32_Graphics_Gdi",
|
||||
"Win32_System_Com",
|
||||
"Win32_UI_Shell",
|
||||
"Win32_UI_WindowsAndMessaging",
|
||||
] }
|
||||
|
||||
[lib]
|
||||
name = "app_lib"
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Request camera access for WebRTC calls.</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Request microphone access for WebRTC calls.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -10,6 +10,7 @@
|
||||
],
|
||||
"permissions": [
|
||||
"updater:default",
|
||||
"global-shortcut:default"
|
||||
"global-shortcut:default",
|
||||
"deep-link:default"
|
||||
]
|
||||
}
|
||||
@@ -2,6 +2,11 @@
|
||||
"identifier": "migrated",
|
||||
"description": "permissions that were migrated from v1",
|
||||
"local": true,
|
||||
"remote": {
|
||||
"urls": [
|
||||
"http://localhost:44548"
|
||||
]
|
||||
},
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
@@ -77,6 +82,10 @@
|
||||
"clipboard-manager:allow-write-text",
|
||||
"core:app:allow-app-show",
|
||||
"core:app:allow-app-hide",
|
||||
"clipboard-manager:default"
|
||||
"clipboard-manager:default",
|
||||
{
|
||||
"identifier": "opener:allow-open-url",
|
||||
"allow": [{ "url": "http://*" }, { "url": "https://*" }]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
{"desktop-capability":{"identifier":"desktop-capability","description":"","local":true,"windows":["main"],"permissions":["updater:default","global-shortcut:default"],"platforms":["macOS","windows","linux"]},"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:default","fs:allow-read-file","fs:allow-write-file","fs:allow-read-dir","fs:allow-copy-file","fs:allow-mkdir","fs:allow-remove","fs:allow-remove","fs:allow-rename","fs:allow-exists","core:window:allow-create","core:window:allow-center","core:window:allow-request-user-attention","core:window:allow-set-resizable","core:window:allow-set-maximizable","core:window:allow-set-minimizable","core:window:allow-set-closable","core:window:allow-set-title","core:window:allow-maximize","core:window:allow-unmaximize","core:window:allow-minimize","core:window:allow-unminimize","core:window:allow-show","core:window:allow-hide","core:window:allow-close","core:window:allow-set-decorations","core:window:allow-set-always-on-top","core:window:allow-set-content-protected","core:window:allow-set-size","core:window:allow-set-min-size","core:window:allow-set-max-size","core:window:allow-set-position","core:window:allow-set-fullscreen","core:window:allow-set-focus","core:window:allow-set-icon","core:window:allow-set-skip-taskbar","core:window:allow-set-cursor-grab","core:window:allow-set-cursor-visible","core:window:allow-set-cursor-icon","core:window:allow-set-cursor-position","core:window:allow-set-ignore-cursor-events","core:window:allow-start-dragging","core:webview:allow-print","shell:allow-execute","shell:allow-open","dialog:allow-open","dialog:allow-save","dialog:allow-message","dialog:allow-ask","dialog:allow-confirm","http:default","notification:default","global-shortcut:allow-is-registered","global-shortcut:allow-register","global-shortcut:allow-register-all","global-shortcut:allow-unregister","global-shortcut:allow-unregister-all","os:allow-platform","os:allow-version","os:allow-os-type","os:allow-family","os:allow-arch","os:allow-exe-extension","os:allow-locale","os:allow-hostname","process:allow-restart","process:allow-exit","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","core:app:allow-app-show","core:app:allow-app-hide","clipboard-manager:default"]}}
|
||||
{"desktop-capability":{"identifier":"desktop-capability","description":"","local":true,"windows":["main"],"permissions":["updater:default","global-shortcut:default"],"platforms":["macOS","windows","linux"]},"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:default","fs:allow-read-file","fs:allow-write-file","fs:allow-read-dir","fs:allow-copy-file","fs:allow-mkdir","fs:allow-remove","fs:allow-remove","fs:allow-rename","fs:allow-exists","core:window:allow-create","core:window:allow-center","core:window:allow-request-user-attention","core:window:allow-set-resizable","core:window:allow-set-maximizable","core:window:allow-set-minimizable","core:window:allow-set-closable","core:window:allow-set-title","core:window:allow-maximize","core:window:allow-unmaximize","core:window:allow-minimize","core:window:allow-unminimize","core:window:allow-show","core:window:allow-hide","core:window:allow-close","core:window:allow-set-decorations","core:window:allow-set-always-on-top","core:window:allow-set-content-protected","core:window:allow-set-size","core:window:allow-set-min-size","core:window:allow-set-max-size","core:window:allow-set-position","core:window:allow-set-fullscreen","core:window:allow-set-focus","core:window:allow-set-icon","core:window:allow-set-skip-taskbar","core:window:allow-set-cursor-grab","core:window:allow-set-cursor-visible","core:window:allow-set-cursor-icon","core:window:allow-set-cursor-position","core:window:allow-set-ignore-cursor-events","core:window:allow-start-dragging","core:webview:allow-print","shell:allow-execute","shell:allow-open","dialog:allow-open","dialog:allow-save","dialog:allow-message","dialog:allow-ask","dialog:allow-confirm","http:default","notification:default","global-shortcut:allow-is-registered","global-shortcut:allow-register","global-shortcut:allow-register-all","global-shortcut:allow-unregister","global-shortcut:allow-unregister-all","os:allow-platform","os:allow-version","os:allow-os-type","os:allow-family","os:allow-arch","os:allow-exe-extension","os:allow-locale","os:allow-hostname","process:allow-restart","process:allow-exit","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","core:app:allow-app-show","core:app:allow-app-hide","clipboard-manager:default",{"identifier":"opener:allow-open-url","allow":[{"url":"http://*"},{"url":"https://*"}]}]}}
|
||||
@@ -2060,6 +2060,174 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`",
|
||||
"type": "string",
|
||||
"const": "opener:default",
|
||||
"markdownDescription": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`"
|
||||
},
|
||||
{
|
||||
"description": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-default-urls",
|
||||
"markdownDescription": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application."
|
||||
},
|
||||
{
|
||||
"description": "Enables the open_path command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-open-path",
|
||||
"markdownDescription": "Enables the open_path command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Enables the open_url command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-open-url",
|
||||
"markdownDescription": "Enables the open_url command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Enables the reveal_item_in_dir command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-reveal-item-in-dir",
|
||||
"markdownDescription": "Enables the reveal_item_in_dir command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the open_path command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-open-path",
|
||||
"markdownDescription": "Denies the open_path command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the open_url command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-open-url",
|
||||
"markdownDescription": "Denies the open_url command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the reveal_item_in_dir command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-reveal-item-in-dir",
|
||||
"markdownDescription": "Denies the reveal_item_in_dir command without any pre-configured scope."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"allow": {
|
||||
"items": {
|
||||
"title": "OpenerScopeEntry",
|
||||
"description": "Opener scope entry.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"app": {
|
||||
"description": "An application to open this url with, for example: firefox.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"description": "A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"app": {
|
||||
"description": "An application to open this path with, for example: xdg-open.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
"path": {
|
||||
"description": "A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"deny": {
|
||||
"items": {
|
||||
"title": "OpenerScopeEntry",
|
||||
"description": "Opener scope entry.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"app": {
|
||||
"description": "An application to open this url with, for example: firefox.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"description": "A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"app": {
|
||||
"description": "An application to open this path with, for example: xdg-open.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
"path": {
|
||||
"description": "A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"description": "Identifier of the permission or permission set.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Identifier"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
@@ -6422,6 +6590,54 @@
|
||||
"const": "notification:deny-show",
|
||||
"markdownDescription": "Denies the show command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`",
|
||||
"type": "string",
|
||||
"const": "opener:default",
|
||||
"markdownDescription": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer\n#### This default permission set includes:\n\n- `allow-open-url`\n- `allow-reveal-item-in-dir`\n- `allow-default-urls`"
|
||||
},
|
||||
{
|
||||
"description": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-default-urls",
|
||||
"markdownDescription": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application."
|
||||
},
|
||||
{
|
||||
"description": "Enables the open_path command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-open-path",
|
||||
"markdownDescription": "Enables the open_path command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Enables the open_url command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-open-url",
|
||||
"markdownDescription": "Enables the open_url command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Enables the reveal_item_in_dir command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-reveal-item-in-dir",
|
||||
"markdownDescription": "Enables the reveal_item_in_dir command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the open_path command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-open-path",
|
||||
"markdownDescription": "Denies the open_path command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the open_url command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-open-url",
|
||||
"markdownDescription": "Denies the open_url command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the reveal_item_in_dir command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-reveal-item-in-dir",
|
||||
"markdownDescription": "Denies the reveal_item_in_dir command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "This permission set configures which\noperating system information are available\nto gather from the frontend.\n\n#### Granted Permissions\n\nAll information except the host name are available.\n\n\n#### This default permission set includes:\n\n- `allow-arch`\n- `allow-exe-extension`\n- `allow-family`\n- `allow-locale`\n- `allow-os-type`\n- `allow-platform`\n- `allow-version`",
|
||||
"type": "string",
|
||||
@@ -6812,6 +7028,23 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"Application": {
|
||||
"description": "Opener scope application.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Open in default application.",
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"description": "If true, allow open with any application.",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"description": "Allow specific application to open with.",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ShellScopeEntryAllowedArg": {
|
||||
"description": "A command argument allowed to be executed by the webview API.",
|
||||
"anyOf": [
|
||||
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 142 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 332 KiB |
@@ -3,29 +3,565 @@
|
||||
windows_subsystem = "windows"
|
||||
)]
|
||||
|
||||
// mod menu;
|
||||
use tauri::{
|
||||
menu::{Menu, MenuItem, PredefinedMenuItem},
|
||||
tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent},
|
||||
webview::{NewWindowResponse, PageLoadEvent, WebviewWindowBuilder},
|
||||
Manager, WebviewUrl,
|
||||
};
|
||||
use tauri_plugin_opener::OpenerExt;
|
||||
|
||||
use tauri::{webview::WebviewWindowBuilder, WebviewUrl};
|
||||
/// Bring the main window to the foreground from the tray / a hidden /
|
||||
/// minimized state. Shared by the tray, single-instance, and deep-link paths.
|
||||
fn show_main(app: &tauri::AppHandle) {
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
let _ = window.show();
|
||||
let _ = window.unminimize();
|
||||
let _ = window.set_focus();
|
||||
}
|
||||
}
|
||||
|
||||
/// Hand a `matrix:` / `matrix.to` URL to the web app by dispatching a DOM
|
||||
/// CustomEvent the client listens for (see useDeepLinkNavigate.ts). Uses
|
||||
/// `eval` so we don't need the @tauri-apps/api event package on the web side.
|
||||
fn forward_deeplink(app: &tauri::AppHandle, url: &str) {
|
||||
show_main(app);
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
if let Ok(json) = serde_json::to_string(url) {
|
||||
let _ = window.eval(&format!(
|
||||
"window.dispatchEvent(new CustomEvent('lotus-deeplink',{{detail:{json}}}))"
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pull the first `matrix:` link out of a process's CLI args (Windows/Linux
|
||||
/// pass deep-link URLs as argv to a freshly launched instance).
|
||||
fn matrix_url_from_args(args: &[String]) -> Option<String> {
|
||||
args.iter().find(|a| a.starts_with("matrix:")).cloned()
|
||||
}
|
||||
|
||||
// Injected into every page before app scripts load.
|
||||
// Patches window.Notification to route through tauri-plugin-notification so
|
||||
// WebView2's default "denied" state never reaches cinny's permission check.
|
||||
// Also patches navigator.permissions.query so the React hook sees "granted".
|
||||
const NOTIFICATION_BRIDGE: &str = r#"(function(){
|
||||
function TauriNotification(title,options){
|
||||
var opts=options||{};
|
||||
try{
|
||||
window.__TAURI_INTERNALS__.invoke('send_notification',{
|
||||
title:String(title),
|
||||
body:opts.body!=null?String(opts.body):undefined
|
||||
}).catch(function(){});
|
||||
}catch(_){}
|
||||
}
|
||||
TauriNotification.prototype=Object.create(EventTarget.prototype);
|
||||
TauriNotification.prototype.constructor=TauriNotification;
|
||||
TauriNotification.prototype.close=function(){};
|
||||
Object.defineProperty(TauriNotification,'permission',{get:function(){return 'granted';},configurable:true});
|
||||
TauriNotification.requestPermission=function(){return Promise.resolve('granted');};
|
||||
TauriNotification.maxActions=0;
|
||||
Object.defineProperty(window,'Notification',{value:TauriNotification,writable:true,configurable:true});
|
||||
var _q=navigator.permissions.query.bind(navigator.permissions);
|
||||
navigator.permissions.query=function(desc){
|
||||
if(desc&&desc.name==='notifications'){
|
||||
return Promise.resolve(Object.assign(new EventTarget(),{state:'granted',onchange:null}));
|
||||
}
|
||||
return _q(desc);
|
||||
};
|
||||
})();"#;
|
||||
|
||||
#[tauri::command]
|
||||
fn send_notification(
|
||||
app: tauri::AppHandle,
|
||||
title: String,
|
||||
body: Option<String>,
|
||||
) -> Result<(), String> {
|
||||
use tauri_plugin_notification::NotificationExt;
|
||||
let mut builder = app.notification().builder().title(&title);
|
||||
if let Some(b) = &body {
|
||||
builder = builder.body(b);
|
||||
}
|
||||
builder.show().map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
struct UpdateInfo {
|
||||
available: bool,
|
||||
version: Option<String>,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn check_for_update(app: tauri::AppHandle) -> Result<UpdateInfo, String> {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
{
|
||||
use tauri_plugin_updater::UpdaterExt;
|
||||
return match app.updater().map_err(|e| e.to_string())?.check().await {
|
||||
Ok(Some(update)) => Ok(UpdateInfo { available: true, version: Some(update.version) }),
|
||||
Ok(None) => Ok(UpdateInfo { available: false, version: None }),
|
||||
Err(e) => Err(e.to_string()),
|
||||
};
|
||||
}
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
Ok(UpdateInfo { available: false, version: None })
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn install_update(app: tauri::AppHandle) -> Result<(), String> {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
{
|
||||
use tauri_plugin_updater::UpdaterExt;
|
||||
if let Some(update) = app
|
||||
.updater()
|
||||
.map_err(|e| e.to_string())?
|
||||
.check()
|
||||
.await
|
||||
.map_err(|e| e.to_string())?
|
||||
{
|
||||
update
|
||||
.download_and_install(|_chunk, _total| {}, || {})
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn set_badge_count(count: u32, window: tauri::Window) -> Result<(), String> {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use windows::{
|
||||
core::{BOOL, PCWSTR},
|
||||
Win32::{
|
||||
Foundation::{COLORREF, HWND, RECT},
|
||||
Graphics::Gdi::{
|
||||
CreateBitmap, CreateCompatibleDC, CreateDIBSection, CreateFontW, CreatePen,
|
||||
CreateSolidBrush, DeleteDC, DeleteObject, DIB_RGB_COLORS, DrawTextW, Ellipse,
|
||||
ReleaseDC, SelectObject, SetBkMode, SetTextColor, BITMAPINFO,
|
||||
BITMAPINFOHEADER, BI_RGB, CLIP_DEFAULT_PRECIS, DEFAULT_CHARSET, DEFAULT_PITCH,
|
||||
DEFAULT_QUALITY, DT_CENTER, DT_SINGLELINE, DT_VCENTER, FF_DONTCARE,
|
||||
FW_BOLD, OUT_DEFAULT_PRECIS, PS_NULL, TRANSPARENT,
|
||||
},
|
||||
UI::{
|
||||
Shell::{ITaskbarList3, TaskbarList},
|
||||
WindowsAndMessaging::{CreateIconIndirect, DestroyIcon, HICON, ICONINFO},
|
||||
},
|
||||
System::Com::{CoCreateInstance, CLSCTX_INPROC_SERVER},
|
||||
},
|
||||
};
|
||||
|
||||
let hwnd = HWND(window.hwnd().map_err(|e| e.to_string())?.0 as _);
|
||||
|
||||
let hicon: Option<HICON> = if count > 0 {
|
||||
let label = if count > 99 {
|
||||
"99+".to_string()
|
||||
} else {
|
||||
count.to_string()
|
||||
};
|
||||
let mut label_wide: Vec<u16> = label.encode_utf16().chain(std::iter::once(0)).collect();
|
||||
|
||||
unsafe {
|
||||
let size = 20i32;
|
||||
let hdc_screen = windows::Win32::Graphics::Gdi::GetDC(None);
|
||||
let hdc = CreateCompatibleDC(Some(hdc_screen));
|
||||
|
||||
let bmi = BITMAPINFO {
|
||||
bmiHeader: BITMAPINFOHEADER {
|
||||
biSize: std::mem::size_of::<BITMAPINFOHEADER>() as u32,
|
||||
biWidth: size,
|
||||
biHeight: -size,
|
||||
biPlanes: 1,
|
||||
biBitCount: 32,
|
||||
biCompression: BI_RGB.0,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
let mut bits: *mut std::ffi::c_void = std::ptr::null_mut();
|
||||
let hbm_color =
|
||||
CreateDIBSection(Some(hdc), &bmi, DIB_RGB_COLORS, &mut bits, None, 0)
|
||||
.map_err(|e| e.to_string())?;
|
||||
// Zero-init so undrawn pixels are fully transparent (CreateDIBSection
|
||||
// does not guarantee zeroed memory; garbage bytes cause a black square).
|
||||
if !bits.is_null() {
|
||||
std::ptr::write_bytes(bits as *mut u8, 0, (size * size * 4) as usize);
|
||||
}
|
||||
let old_bm = SelectObject(hdc, hbm_color.into());
|
||||
|
||||
let hbrush = CreateSolidBrush(COLORREF(0x003030DD));
|
||||
let old_brush = SelectObject(hdc, hbrush.into());
|
||||
let hpen = CreatePen(PS_NULL, 0, COLORREF(0));
|
||||
let old_pen = SelectObject(hdc, hpen.into());
|
||||
let _ = Ellipse(hdc, 0, 0, size, size);
|
||||
|
||||
let hfont = CreateFontW(
|
||||
14,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
FW_BOLD.0 as i32,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
DEFAULT_CHARSET,
|
||||
OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS,
|
||||
DEFAULT_QUALITY,
|
||||
(DEFAULT_PITCH.0 | FF_DONTCARE.0) as u32,
|
||||
windows::core::w!("Segoe UI"),
|
||||
);
|
||||
let old_font = SelectObject(hdc, hfont.into());
|
||||
SetTextColor(hdc, COLORREF(0x00FFFFFF));
|
||||
let _ = SetBkMode(hdc, TRANSPARENT);
|
||||
let mut rect = RECT { left: 0, top: 0, right: size, bottom: size };
|
||||
let label_len = label_wide.len() - 1;
|
||||
let _ = DrawTextW(
|
||||
hdc,
|
||||
&mut label_wide[..label_len],
|
||||
&mut rect,
|
||||
DT_CENTER | DT_VCENTER | DT_SINGLELINE,
|
||||
);
|
||||
|
||||
SelectObject(hdc, old_brush);
|
||||
SelectObject(hdc, old_pen);
|
||||
SelectObject(hdc, old_font);
|
||||
SelectObject(hdc, old_bm);
|
||||
let _ = DeleteObject(hbrush.into());
|
||||
let _ = DeleteObject(hpen.into());
|
||||
let _ = DeleteObject(hfont.into());
|
||||
|
||||
// GDI drawing leaves the alpha channel at 0 for all pixels.
|
||||
// Set alpha=255 for every painted pixel so Windows uses per-pixel
|
||||
// alpha compositing instead of falling back to the opaque mask,
|
||||
// which would render unpainted corner pixels as a black square.
|
||||
let pixel_count = (size * size) as usize;
|
||||
let pixels =
|
||||
std::slice::from_raw_parts_mut(bits as *mut u32, pixel_count);
|
||||
for pixel in pixels.iter_mut() {
|
||||
if *pixel != 0 {
|
||||
*pixel |= 0xFF00_0000u32;
|
||||
}
|
||||
}
|
||||
|
||||
let hbm_mask = CreateBitmap(size, size, 1, 1, None);
|
||||
if hbm_mask.0 as usize == 0 {
|
||||
let _ = DeleteObject(hbm_color.into());
|
||||
return Err("CreateBitmap failed".to_string());
|
||||
}
|
||||
|
||||
let icon_info = ICONINFO {
|
||||
fIcon: BOOL(1),
|
||||
xHotspot: 0,
|
||||
yHotspot: 0,
|
||||
hbmMask: hbm_mask,
|
||||
hbmColor: hbm_color,
|
||||
};
|
||||
let hicon = CreateIconIndirect(&icon_info).map_err(|e| {
|
||||
let _ = DeleteObject(hbm_color.into());
|
||||
let _ = DeleteObject(hbm_mask.into());
|
||||
e.to_string()
|
||||
})?;
|
||||
|
||||
let _ = DeleteObject(hbm_color.into());
|
||||
let _ = DeleteObject(hbm_mask.into());
|
||||
let _ = DeleteDC(hdc);
|
||||
let _ = ReleaseDC(None, hdc_screen);
|
||||
|
||||
Some(hicon)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let taskbar: ITaskbarList3 =
|
||||
CoCreateInstance(&TaskbarList, None, CLSCTX_INPROC_SERVER)
|
||||
.map_err(|e| e.to_string())?;
|
||||
taskbar.HrInit().map_err(|e| e.to_string())?;
|
||||
taskbar
|
||||
.SetOverlayIcon(hwnd, hicon.unwrap_or_default(), PCWSTR::null())
|
||||
.map_err(|e| e.to_string())?;
|
||||
if let Some(icon) = hicon {
|
||||
let _ = DestroyIcon(icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Held in managed state so the tray's unread overlay can be updated at runtime.
|
||||
/// Keeping the TrayIcon handle here also keeps the tray alive.
|
||||
struct TrayUnreadState {
|
||||
tray: tauri::tray::TrayIcon,
|
||||
base_rgba: Vec<u8>,
|
||||
width: u32,
|
||||
height: u32,
|
||||
}
|
||||
|
||||
/// Paint a small white-ringed red "unread" dot into the bottom-right corner of
|
||||
/// an RGBA buffer, in place. Cross-platform (operates on raw pixels).
|
||||
fn draw_unread_dot(rgba: &mut [u8], width: u32, height: u32) {
|
||||
let w = width as i32;
|
||||
let h = height as i32;
|
||||
if w <= 0 || h <= 0 {
|
||||
return;
|
||||
}
|
||||
let r = ((w.min(h) as f32) * 0.30) as i32;
|
||||
let ring = ((r as f32) * 0.18).max(1.0) as i32;
|
||||
let cx = w - r - ((w as f32) * 0.06) as i32;
|
||||
let cy = h - r - ((h as f32) * 0.06) as i32;
|
||||
for y in (cy - r - ring).max(0)..(cy + r + ring).min(h) {
|
||||
for x in (cx - r - ring).max(0)..(cx + r + ring).min(w) {
|
||||
let dx = x - cx;
|
||||
let dy = y - cy;
|
||||
let dist2 = dx * dx + dy * dy;
|
||||
let idx = ((y * w + x) as usize) * 4;
|
||||
if idx + 3 >= rgba.len() {
|
||||
continue;
|
||||
}
|
||||
if dist2 <= r * r {
|
||||
rgba[idx] = 0xDD;
|
||||
rgba[idx + 1] = 0x30;
|
||||
rgba[idx + 2] = 0x30;
|
||||
rgba[idx + 3] = 0xFF;
|
||||
} else if dist2 <= (r + ring) * (r + ring) {
|
||||
rgba[idx] = 0xFF;
|
||||
rgba[idx + 1] = 0xFF;
|
||||
rgba[idx + 2] = 0xFF;
|
||||
rgba[idx + 3] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Overlay (or clear) the unread dot on the tray icon.
|
||||
#[tauri::command]
|
||||
fn set_tray_unread(unread: bool, state: tauri::State<'_, TrayUnreadState>) -> Result<(), String> {
|
||||
let mut rgba = state.base_rgba.clone();
|
||||
if unread {
|
||||
draw_unread_dot(&mut rgba, state.width, state.height);
|
||||
}
|
||||
let icon = tauri::image::Image::new_owned(rgba, state.width, state.height);
|
||||
state.tray.set_icon(Some(icon)).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// Flash the taskbar button to draw attention (e.g. a new mention while the
|
||||
/// window is unfocused). Clears automatically once the window is focused.
|
||||
#[tauri::command]
|
||||
fn flash_window(window: tauri::Window) -> Result<(), String> {
|
||||
window
|
||||
.request_user_attention(Some(tauri::UserAttentionType::Informational))
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
pub fn run() {
|
||||
let port: u16 = 44548;
|
||||
let context = tauri::generate_context!();
|
||||
let builder = tauri::Builder::default();
|
||||
|
||||
// #[cfg(target_os = "macos")]
|
||||
// {
|
||||
// builder = builder.menu(menu::menu());
|
||||
// }
|
||||
#[allow(unused_mut)]
|
||||
let mut builder = tauri::Builder::default();
|
||||
|
||||
builder
|
||||
// Single-instance MUST be registered first: a second launch focuses the
|
||||
// existing window (and forwards any matrix: link) instead of colliding on
|
||||
// the localhost port. Desktop-only plugin.
|
||||
#[cfg(desktop)]
|
||||
{
|
||||
builder = builder.plugin(tauri_plugin_single_instance::init(|app, argv, _cwd| {
|
||||
show_main(app);
|
||||
if let Some(url) = matrix_url_from_args(&argv) {
|
||||
forward_deeplink(app, &url);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
builder = builder
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
set_badge_count,
|
||||
set_tray_unread,
|
||||
flash_window,
|
||||
send_notification,
|
||||
check_for_update,
|
||||
install_update,
|
||||
])
|
||||
.plugin(tauri_plugin_localhost::Builder::new(port).build())
|
||||
.plugin(tauri_plugin_window_state::Builder::default().build())
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.plugin(tauri_plugin_notification::init())
|
||||
.plugin(tauri_plugin_deep_link::init());
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
{
|
||||
builder = builder.plugin(tauri_plugin_updater::Builder::new().build());
|
||||
}
|
||||
|
||||
builder
|
||||
.setup(move |app| {
|
||||
let url = format!("http://localhost:{}", port).parse().unwrap();
|
||||
let window_url = WebviewUrl::External(url);
|
||||
WebviewWindowBuilder::new(app, "main".to_string(), window_url)
|
||||
.title("Cinny")
|
||||
// --- System tray: keeps Lotus Chat running in the background so
|
||||
// notifications keep arriving after the window is closed-to-tray. ---
|
||||
let base_icon = app.default_window_icon().cloned();
|
||||
let open_item = MenuItem::with_id(app, "open", "Open Lotus Chat", true, None::<&str>)?;
|
||||
let quit_item = MenuItem::with_id(app, "quit", "Quit Lotus Chat", true, None::<&str>)?;
|
||||
let separator = PredefinedMenuItem::separator(app)?;
|
||||
let tray_menu = Menu::with_items(app, &[&open_item, &separator, &quit_item])?;
|
||||
let tray = TrayIconBuilder::with_id("main-tray")
|
||||
.icon(base_icon.clone().expect("bundled window icon"))
|
||||
.tooltip("Lotus Chat")
|
||||
.menu(&tray_menu)
|
||||
.show_menu_on_left_click(false)
|
||||
.on_menu_event(|app, event| match event.id.as_ref() {
|
||||
"open" => show_main(app),
|
||||
"quit" => app.exit(0),
|
||||
_ => {}
|
||||
})
|
||||
.on_tray_icon_event(|tray, event| {
|
||||
if let TrayIconEvent::Click {
|
||||
button: MouseButton::Left,
|
||||
button_state: MouseButtonState::Up,
|
||||
..
|
||||
} = event
|
||||
{
|
||||
let app = tray.app_handle();
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
if window.is_visible().unwrap_or(false) {
|
||||
let _ = window.hide();
|
||||
} else {
|
||||
show_main(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.build(app)?;
|
||||
|
||||
// Keep the tray handle (and base icon pixels) in managed state so
|
||||
// set_tray_unread can re-render the icon at runtime.
|
||||
if let Some(img) = base_icon {
|
||||
let base_rgba = img.rgba().to_vec();
|
||||
let (width, height) = (img.width(), img.height());
|
||||
app.manage(TrayUnreadState {
|
||||
tray,
|
||||
base_rgba,
|
||||
width,
|
||||
height,
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
let window_url = WebviewUrl::App(Default::default());
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
let window_url = {
|
||||
let url = format!("http://localhost:{}", port).parse().unwrap();
|
||||
WebviewUrl::External(url)
|
||||
};
|
||||
|
||||
let app_handle = app.handle().clone();
|
||||
let window = WebviewWindowBuilder::new(app, "main".to_string(), window_url)
|
||||
.title("Lotus Chat")
|
||||
// First-run defaults; tauri-plugin-window-state restores geometry
|
||||
// on later launches.
|
||||
.inner_size(1100.0, 720.0)
|
||||
.min_inner_size(480.0, 600.0)
|
||||
.center()
|
||||
// Start hidden and reveal once the page has painted, to avoid the
|
||||
// white launch flash.
|
||||
.visible(false)
|
||||
.initialization_script(NOTIFICATION_BRIDGE)
|
||||
.disable_drag_drop_handler()
|
||||
.on_page_load(|window, payload| {
|
||||
if matches!(payload.event(), PageLoadEvent::Finished) {
|
||||
let _ = window.show();
|
||||
}
|
||||
})
|
||||
.on_new_window(move |url, _features| {
|
||||
let _ = app_handle.opener().open_url(url.as_str(), None::<&str>);
|
||||
NewWindowResponse::Deny
|
||||
})
|
||||
.build()?;
|
||||
|
||||
// Close-to-tray: hide instead of exiting; the app is quit explicitly
|
||||
// from the tray menu.
|
||||
let window_for_close = window.clone();
|
||||
window.on_window_event(move |event| {
|
||||
if let tauri::WindowEvent::CloseRequested { api, .. } = event {
|
||||
api.prevent_close();
|
||||
let _ = window_for_close.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Failsafe: never leave the window stuck hidden if the page-load
|
||||
// event doesn't fire for some reason.
|
||||
let window_for_show = window.clone();
|
||||
std::thread::spawn(move || {
|
||||
std::thread::sleep(std::time::Duration::from_secs(8));
|
||||
let _ = window_for_show.show();
|
||||
});
|
||||
|
||||
// Deep links (matrix:): route both the cold-start case and the
|
||||
// already-running case (forwarded via single-instance argv) into the
|
||||
// web client.
|
||||
{
|
||||
use tauri_plugin_deep_link::DeepLinkExt;
|
||||
// Runtime scheme registration is a Linux/Windows-only API; macOS
|
||||
// registers the scheme from the bundle config at build time.
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
let _ = app.deep_link().register_all();
|
||||
let deep_link_handle = app.handle().clone();
|
||||
app.deep_link().on_open_url(move |event| {
|
||||
for url in event.urls() {
|
||||
forward_deeplink(&deep_link_handle, url.as_str());
|
||||
}
|
||||
});
|
||||
if let Some(url) = matrix_url_from_args(&std::env::args().collect::<Vec<_>>()) {
|
||||
forward_deeplink(&app.handle().clone(), &url);
|
||||
}
|
||||
}
|
||||
|
||||
// Windows 11 Mica backdrop. The app paints an opaque TDS background,
|
||||
// so this is subtle (mainly window chrome); harmless if unsupported.
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let _ = window_vibrancy::apply_mica(&window, Some(true));
|
||||
}
|
||||
|
||||
// Auto-grant camera, microphone, and notification permissions in WebView2.
|
||||
#[cfg(target_os = "windows")]
|
||||
window.with_webview(|webview| {
|
||||
use webview2_com::{
|
||||
Microsoft::Web::WebView2::Win32::{
|
||||
COREWEBVIEW2_PERMISSION_KIND,
|
||||
COREWEBVIEW2_PERMISSION_KIND_CAMERA,
|
||||
COREWEBVIEW2_PERMISSION_KIND_MICROPHONE,
|
||||
COREWEBVIEW2_PERMISSION_KIND_NOTIFICATIONS,
|
||||
COREWEBVIEW2_PERMISSION_STATE_ALLOW,
|
||||
},
|
||||
PermissionRequestedEventHandler,
|
||||
};
|
||||
|
||||
let controller = webview.controller();
|
||||
if let Ok(core) = unsafe { controller.CoreWebView2() } {
|
||||
let handler = PermissionRequestedEventHandler::create(Box::new(
|
||||
|_sender, args| {
|
||||
if let Some(args) = args {
|
||||
let mut kind = COREWEBVIEW2_PERMISSION_KIND(0);
|
||||
unsafe { args.PermissionKind(&mut kind) }?;
|
||||
if kind == COREWEBVIEW2_PERMISSION_KIND_MICROPHONE
|
||||
|| kind == COREWEBVIEW2_PERMISSION_KIND_CAMERA
|
||||
|| kind == COREWEBVIEW2_PERMISSION_KIND_NOTIFICATIONS
|
||||
{
|
||||
unsafe {
|
||||
args.SetState(COREWEBVIEW2_PERMISSION_STATE_ALLOW)
|
||||
}?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
));
|
||||
let mut token = Default::default();
|
||||
let _ = unsafe { core.add_PermissionRequested(&handler, &mut token) };
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.run(context)
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
use tauri::menu::{MenuBuilder, SubmenuBuilder};
|
||||
use tauri::AppHandle;
|
||||
|
||||
pub fn menu() -> tauri::menu::Menu {
|
||||
let app_menu = SubmenuBuilder::new(app, "Cinny")
|
||||
.about(Some(Default::default()))
|
||||
.separator()
|
||||
.hide()
|
||||
.hide_others()
|
||||
.show_all()
|
||||
.separator()
|
||||
.quit()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let edit_menu = SubmenuBuilder::new(app, "Edit")
|
||||
.undo()
|
||||
.redo()
|
||||
.separator()
|
||||
.cut()
|
||||
.copy()
|
||||
.paste()
|
||||
.select_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let view_menu = SubmenuBuilder::new(app, "View")
|
||||
.fullscreen() // `.fullscreen()` works instead of `.enter_fullscreen()`
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let window_menu = SubmenuBuilder::new(app, "Window")
|
||||
.minimize()
|
||||
.build() // no `.zoom()` method directly available
|
||||
.unwrap();
|
||||
|
||||
MenuBuilder::new(app)
|
||||
.item(&app_menu)
|
||||
.item(&edit_menu)
|
||||
.item(&view_menu)
|
||||
.item(&window_menu)
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
@@ -6,6 +6,12 @@
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": "",
|
||||
"webviewInstallMode": {
|
||||
"type": "downloadBootstrapper"
|
||||
},
|
||||
"nsis": {
|
||||
"installMode": "currentUser"
|
||||
},
|
||||
"wix": {
|
||||
"bannerPath": "wix/banner.bmp",
|
||||
"dialogImagePath": "wix/dialogImage.bmp"
|
||||
@@ -45,21 +51,26 @@
|
||||
"beforeDevCommand": "cd cinny && npm start",
|
||||
"devUrl": "http://localhost:8080"
|
||||
},
|
||||
"productName": "Cinny",
|
||||
"productName": "Lotus Chat",
|
||||
"mainBinaryName": "cinny",
|
||||
"version": "4.11.1",
|
||||
"identifier": "in.cinny.app",
|
||||
"version": "4.12.2",
|
||||
"identifier": "org.lotusguild.lotus-chat",
|
||||
"plugins": {
|
||||
"updater": {
|
||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDE2NDc3NDBGMTAzNTk1NUYKUldSZmxUVVFEM1JIRnRuMjVRTkFOQ21lUFI5KzRMU0s4OWtBS1RNRUVCNE9LcE9GcExNZ2M2NHoK",
|
||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDM1N0Y0RThCQTJEQzY1NTkKUldSWlpkeWlpMDUvTlVjejMzN0E1U0FiaVpLK05QVkRXdWlMMm1NNUprMXAvTGZSbU5maVovNmwK",
|
||||
"endpoints": [
|
||||
"https://github.com/cinnyapp/cinny-desktop/releases/download/tauri/release.json"
|
||||
"https://code.lotusguild.org/LotusGuild/cinny-desktop/releases/download/latest/release.json"
|
||||
]
|
||||
},
|
||||
"deep-link": {
|
||||
"desktop": {
|
||||
"schemes": ["matrix"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"app": {
|
||||
"security": {
|
||||
"csp": "default-src 'self' blob: data: filesystem: ws: wss: http: https: tauri:; script-src 'self' 'unsafe-eval' 'unsafe-inline' blob: data: filesystem: ws: wss: http: https: tauri:; img-src 'self' data: blob: filesystem: http: https:; connect-src 'self' ipc: ws: wss: http: https: http://ipc.localhost"
|
||||
"csp": "default-src 'self' blob: data: filesystem: ws: wss: http: https: tauri:; script-src 'self' 'unsafe-eval' 'unsafe-inline' blob: data: filesystem: ws: wss: http: https: tauri:; style-src 'self' 'unsafe-inline' blob: data: filesystem: http: https:; img-src 'self' data: blob: filesystem: http: https:; media-src 'self' blob: data: mediastream:; connect-src 'self' blob: ipc: ws: wss: http: https: http://ipc.localhost"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const char *appdir = "/root/linuxdeploy-root";
|
||||
char apprun[256], ldbin[256], new_path[4096], new_ldpath[4096];
|
||||
struct stat st;
|
||||
|
||||
snprintf(apprun, sizeof(apprun), "%s/AppRun", appdir);
|
||||
snprintf(ldbin, sizeof(ldbin), "%s/usr/bin/linuxdeploy", appdir);
|
||||
|
||||
/* Strip --appimage-extract-and-run: AppImage runtime flag, not a linuxdeploy flag */
|
||||
char **new_argv = malloc((argc + 1) * sizeof(char *));
|
||||
int new_argc = 0;
|
||||
new_argv[new_argc++] = argv[0];
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--appimage-extract-and-run") != 0)
|
||||
new_argv[new_argc++] = argv[i];
|
||||
}
|
||||
new_argv[new_argc] = NULL;
|
||||
|
||||
setenv("APPDIR", appdir, 1);
|
||||
|
||||
char *old_path = getenv("PATH");
|
||||
snprintf(new_path, sizeof(new_path), "%s/usr/bin:%s", appdir, old_path ? old_path : "");
|
||||
setenv("PATH", new_path, 1);
|
||||
|
||||
char *old_ldpath = getenv("LD_LIBRARY_PATH");
|
||||
snprintf(new_ldpath, sizeof(new_ldpath), "%s/usr/lib:%s/usr/lib/x86_64-linux-gnu:%s",
|
||||
appdir, appdir, old_ldpath ? old_ldpath : "");
|
||||
setenv("LD_LIBRARY_PATH", new_ldpath, 1);
|
||||
|
||||
/* Write diagnostic log visible in the always() post-step */
|
||||
FILE *log = fopen("/tmp/ld-wrapper.log", "w");
|
||||
if (log) {
|
||||
fprintf(log, "APPDIR=%s\n", appdir);
|
||||
fprintf(log, "AppRun exists: %s\n", stat(apprun, &st) == 0 ? "yes" : "NO");
|
||||
fprintf(log, "linuxdeploy exists: %s\n", stat(ldbin, &st) == 0 ? "yes" : "NO");
|
||||
fprintf(log, "argc=%d new_argc=%d\n", argc, new_argc);
|
||||
fprintf(log, "args:");
|
||||
for (int i = 0; i < new_argc; i++) fprintf(log, " [%s]", new_argv[i]);
|
||||
fprintf(log, "\nPATH=%s\n", getenv("PATH") ? getenv("PATH") : "(null)");
|
||||
fclose(log);
|
||||
}
|
||||
|
||||
if (stat(ldbin, &st) == 0)
|
||||
execv(ldbin, new_argv);
|
||||
execv(apprun, new_argv);
|
||||
return 1;
|
||||
}
|
||||